views:

808

answers:

2

Selection count, .SelectedItems.Count, does not change when the Selected property is set to true on an item in the Items collection of an ListView.

Example:

  lvPept.SelectedItems.Clear()
  lvPept.Items(6).Selected = True
  Dim newLen As Integer = lvPept.SelectedItems.Count

lvPept is a ListView and contains 10 elements.

newLen is expected to be 1, but is 0 when the problem occurs and the SelectedIndexChanged event is not fired. With other datasets it is 1 as expected and the SelectedIndexChanged event is fired.

Under what circumstance or in what state can lvPept be in for this to happen? BeginUpdate()/EndUpdate() is not used with lvPept.

Background:

I am trying to track down a problem one of the users of my open source .NET application, MSQuant (http://msquant.sourceforge.net/), encountered.

I have run out of ideas of what could be the cause of this problem.

The problem is reproducible and I can reproduce it in my development environment, Visual Studio 2008. It seems to be independent of the Windows version (Win2000/WinXP 32 bit/ WinXP 64 bit), the .NET runtime version (2.0/3.5) and Visual Studio version (2005/2008).

Other context: the application is written in VB.NET and in C# and is a WinForms application. The source code for the class in question is at http://shrinkster.com/14bg. The form class that the ListView is in was initially generated by one of earliest official versions of Visual Studio that supported .NET, ca. 2002.

Update 1: as I have both a working case and a broken case I have compared the content of lvPept. The only difference except for properties "Handle", "MousePosition" and "TopItem" (as it is a different protein with different peptides) is property "Created". It was False for the broken case. It makes sense that a partly constructed object can not function properly, but how can it happen?

Update 2: property "Created" being false turned out to be a good lead. I think the real problem was doing this at construction time and not at form load time. I have now added ASSERTs for property "Created", refactored and changed all the operations to happen at form load time. It now works as expected and the user with the problem has got a new version of the application.

The old bad way had been in there since the application's inception in 2002. I am just wondering if some experts could shred light on why it worked 99.9% of the time and only failed in a few cases and reproducably so.

+1  A: 

That's an interesting one.

The only thing that I think could make this happen is if the ListView didn't realize that the ListItem had changed it's "Selected" value and therefore doesn't update its selected item collections.

The .SelectedItems property is not necessarily generated each time you get the property - if you reflect the System.Windows.Forms assembly:

    if (this.selectedListViewItemCollection == null)
    {
        this.selectedListViewItemCollection = new SelectedListViewItemCollection(this);
    }
    return this.selectedListViewItemCollection;

So I'm inclined to think that you're getting an out-of-date selectedListViewItemCollection.

I would try instead of changing the Selected property at the Item level, try instead adding the selected index to the .SelectedIndices property of the ListView and see if that works. That way the ListView isn't relying on picking up a ListViewItem change.

routeNpingme
A: 

I believe you also have to call ListView.Select() in order to fire the SelectedIndexChanged event.

lvPept.SelectedItems.Clear()
lvPept.Items(6).Selected = True
lvPept.Select()
Dim newLen As Integer = lvPept.SelectedItems.Count
scottm
I have now tried to add lsPept.Select(). It did not make any difference.
Peter Mortensen
Oops! typo, it was supposed to be lvPept.Select()!
scottm