Menu

#174 Unable to cast object of type 'ListViewSubItem' to type 'BrightIdeasSoftware.OLVListSubItem'.

C#_v2.9
closed
None
1
2019-11-15
2018-08-16
Thracx
No

[v2.9.1] I've fixed a bug where an unsafe cast operation can cause InvalidCastExceptions. From what I can tell, it only seems to happen when there are no columns which can happen sometimes in my threading code that might load rows before columns are loaded, or just because the user happens to mouse over the area a specific times. Since these exceptions happen purely in the OLV Win32 event code, there isn't a (good) way to catch and ignore the exceptions (although you can do it in an CurrentDomainUnhandledException).

The fix for me was to change a casting operation to use the 'as' operator, which returns null instead of an exception being thrown. In OLVListItem.cs#247:
return this.SubItems[index] as OLVListSubItem;

While I personally didn't encounter it here, it's also worth changing Renderers.cs#970 to:
this.SubItem = e.SubItem as OLVListSubItem;

In the Changelog, the comment on 2010.08.18, JPP seems to mention this same issue as being old but fixed. Perhaps it was re-introduced while adding later features, like mouse HitTest which is often mentioned in the trace logs.

Discussion

  • Phillip Piper

    Phillip Piper - 2018-09-01

    So, this only happens when there are no columns? That's an important details I've not heard before. I must admit I've never tried that as a test case.

    Thanks for this report. I'll look into it further.

     
  • Phillip Piper

    Phillip Piper - 2018-09-01
    • status: open --> accepted
    • assigned_to: Phillip Piper
     
  • Phillip Piper

    Phillip Piper - 2018-09-01

    Copied from previous ticket:

    An InvalidCastException can occur when processing OLVListSubItems. Changing most references to the base type ListViewItem.ListViewSubItem and only casting when needed (rare) fixes the issue.

    This might be isolated to the TreeListView.

    Changes Needed:
    ObjectListView.LowLevelHitTest, return from GetSubItem
    ObjectListView.UpdateHotRow, return from GetSubItem
    ObjectListView.DrawAllDecorations, foreach loop
    ObjectListView.TriggerFormatRowEvent, foreach loop

     
  • Phillip Piper

    Phillip Piper - 2018-09-01

    In general, it should be impossible for a ListViewItem.ListViewSubItem to end up within an ObjectListView. So long as developers don't mess with the ListViewItems directly, it shouldn't happen.

    However, ListViews are complicated beasts and it could be that there is an exceptional path that I haven't considered (like something odd happens when there are 0 columns).

     
  • Phillip Piper

    Phillip Piper - 2018-09-01

    And indeed there is! Using dotPeek I can see in ListViewItem.cs, there is this code:

    public ListViewSubItemCollection SubItems {
        get {
            if (SubItemCount == 0) {
                subItems = new ListViewSubItem[1];
                subItems[0] = new ListViewSubItem(this, string.Empty);
                SubItemCount = 1;
            }
    
            if (listViewSubItemCollection == null) {
                listViewSubItemCollection = new ListViewSubItemCollection(this);
            }
            return listViewSubItemCollection;
        }
    }
    

    So, if your ListViewItem has no sub-items -- for example, if there were no columns in the control -- this code will helpfully make an empty one for you! Which breaks my pre-conditions :(

    I will put a fixed version of the code into the repo today.

    Thanks for noting that there were possibly no columns in the control when this happened. That was the crucial piece of information I needed that I didn't know from other reports!

     

    Last edit: Phillip Piper 2018-09-01
    • Thracx

      Thracx - 2018-09-04

      This is exactly what I expected - some 'magic' generation of items/SubItems, particularly in uncommon scenarios. (This also might help explain why it can happen when there are items in the list - if there's only 1 column, the above auto-generation of subitems would still happen!)

      Glad to help! It took quite a bit of digging to narrow down, but since my local copy of the code already had fixes for other occurences, it allowed the no-column observation to come through.

       
  • Phillip Piper

    Phillip Piper - 2018-09-01

    The repo has been updated with the fixed code.

    If you can, check it out and see if it fixes the problem for you.

     
  • Thracx

    Thracx - 2018-09-04

    I will try to get my source updated, but it might take some time. I have had a hard time following updates to OLV since it seems like the version is always '2.9.1' while there have indeed been updates. I am not sure if all my local fixes have been applied or not, merging is never fun but I recall them all being very minor so wish me luck!

     
  • Phillip Piper

    Phillip Piper - 2018-10-06
    • status: accepted --> closed
     
  • Paolo Marani

    Paolo Marani - 2019-11-14

    Hi Guys, i have replaced a plain vanilla ListItemView with this revamped control, everything compiles, but i always get this "cast BrightIdeasSoftware.OLVListItem" error every time.
    It is unusable if this is not addressed, because as far as i run my project and form is displayed, an immediate untrappable crash occurs. How is it possible that this bug get unnoticed ? I'm under 2.9.1
    Any workaround ? I've havent change a single line of code from my previous ListView, and i just added some SubItems after calling lv .Items.Add()

     

    Last edit: Paolo Marani 2019-11-15
  • Thracx

    Thracx - 2019-11-14

    This control is completely different from a normal ListView, are you sure you've changed all the non-object based calls into OLV appropriate calls?

     
  • Paolo Marani

    Paolo Marani - 2019-11-15

    Well, as far as i understand, this component is a subclass/wrapper of a standard listview, so i expect it should work as "drop in" out of the box when extra features are not in use. In my humble opinion, the WinProc should check if you are using standard ListViewItems and keep compatibility with the standard listview as much as possible, and add new features only when switching to OLVListItem. I suggest adding unit testing to ensure legacy addition of item and subitems do work as expected. The WinProc should be bullet proof, otherwise very nasty untrappable exceptions may occur.
    Which "appropriate" calls are supposed to be used to avoid such exceptions ? At this time i have no choice then adding source code directly to the project, because nuget package are compiled in release and runtime seem not so reliable as i expected..

     

    Last edit: Paolo Marani 2019-11-15
  • Paolo Marani

    Paolo Marani - 2019-11-15

    I apologize i havent properly readed all the documentations, including the fundamental "Getting Started/Unlearn you must" (http://objectlistview.sourceforge.net/cs/gettingStarted.html#gettingstarted) where it is perfectly stated that this is not at all a drop-in replacement for a listview when a lot of boilerplate is already in place. I'll give myself another chance :)

     

    Last edit: Paolo Marani 2019-11-15

Log in to post a comment.