locked
Virtual ListView - Selected Item Trouble RRS feed

  • Question

  • What I am trying to do is have a virtual listview that grows even as the user is using it. So every second a couple hundred items could be added - the scrollbar maximum will update and if the user happens to scroll to the end they will see the newly added items, even as more are being added.

    I have a ListView control bound to a custom IList implementation so that virtualization works. The IList class also implements INotifyCollectionChanged so that items added to the underlying collection can be detected by the listview so that it updates. As it's virtual all I really want to do is for the listview to detect that the collection Count has changed so that it updates it's scrollbars accordingly. I shouldn't really need to tell it what items have been added, it can query back into the IList indexer to get specific items (the reason why it's a custom IList implementation is because I have the indexer fetching items as needed and I couldn't find a framework class to do that)

    When new items are "added" to the underlying collection (possibly hundreds in one go), I call the CollectionChanged event so the listview can detect the change and expand it's scrollbars accordingly so that the user can scroll down to see the new items. But I quickly discovered that NotifyCollectionChangedAction.Add only supports notifying the listview that a single item has been added to the collection - and worse you have to pass it a reference to that item. Anyway calling CollectionChanged once for every added item causes too much slowdown. Calling it just once with the last item added in a bid to trick the listview into realizing the collection Count has increased by 100 doesn't work either (the listview still interprets that the item count has only increased by one).

    The alternative that does work is to call CollectionChanged with NotifyCollectionChangedAction.Reset. That causes the listview to refresh all items and it picks up the fact that the Count property has changed. The scrollbar then work fine and I can scroll through all the new items and see them appear as they are added.

    However the Reset causes the listview to go request all the items in the visible view again. Because the items are virtual I end up passing back different instances for the items than were contained in the listview before the reset. Because the instances are different the selected item gets lost (because listview seems to remember selecteditems on reference rather than index)

    I am using single selection mode so it should be possible for me to cache the item that is currently selected so that I can maintain the selection. That's fine.

    The big problem however is that even when the selection works using the mouse, keyboard select doesn't work. If I use the down cursor key to select the next item in the list and reset has just been called, the selection jumps to the first item in the list (index 0) instead of the item below the previously selected item. It's as if it's lost track of where the selected item is in the list because of the reset.

    I guess I have two questions.

    Am I stuck with using Reset? Is there no way to just tell the listview that the collection count has changed so that the listview will then query any items if and when it needs them?

    And if I am stuck with reset, what's up with the keyboard item selection?

    I can supply source code example if necessary I just need to tidy it up quite a lot because I have messed it up entirely trying to find out what's going on. Hopefully though what I have mentioned above rings an alarm bell that I've done something wrong.

    Edit: sorry I didn't realize the above question had turned into an essay until after I posted it and saw it fills the screen.

    Tuesday, December 21, 2010 8:49 PM

All replies

  • Not sure if this will help, but it does a lot to explain what is going on:

    http://bea.stollnitz.com/blog/?p=378

    the first few comments may also be of interest.


    John Fenton
    Wordmasters Direct Mail and Data Processing Services
    Wednesday, December 22, 2010 3:21 AM
  • Hi Oblong,

    Thanks for your question.

    As far as I know, ListView/ListBox consider the current focused container(ListViewItem/ListBoxItem) to be the current item of the Keyboard navigation. So we can set focus to the container of the SelectedItem to fix the keyboard navigation issue.

    For example, after you set back the SelectedItem, try the following code to fix the keyboard selection.

       Object selectedItem = listview.SelectedItem;
       ListViewItem container = selectedItem as ListViewItem;
       if (container == null)
       {
        container = listview.ItemContainerGenerator.ContainerFromItem(selectedItem) as ListViewItem;
       }
    
       if (container != null)
       {
        container.Focus();
       }
    

    Hope this helps.

    If you still have any doubts or concerns about this issue, please feel free to let me know.


    Best regards,
    Min Zhu [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, December 23, 2010 6:23 AM
  • Hi Oblong,

    Just checking in to see if the information was helpful. Please let us know if you would like further assistance.

    Have a nice day!


    Best regards,
    Min Zhu [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, December 27, 2010 1:36 AM
  • Thanks, unfortunately playing with the focused item didn't help. I may or may not have done it correctly, but I have decided to stop fighting the WPF listview control for now and move on. I will abandon use of NotifyCollectionChangedAction.Reset and use NotifyCollectionChangedAction.Add instead. The upside is that functionally everything now works. The downside is that a CollectionChanged event must be raised for every item added to the listview, which at the fastest rate of load results in the UI locking up. To prevent that I will try loading the data at a slower rate. If the load time is unacceptable I will have to revist use of Reset but I hope I won't have to. Thanks for the help anyway.

    Wednesday, December 29, 2010 5:32 PM
  • Hi Oblong,

    Thanks for your reply and update.

    If you have any other questions or concerns, please do not hesitate to contact us. It is always our pleasure to be of assistance.

    Have a nice day!


    Best regards,
    Min Zhu [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, December 30, 2010 3:10 AM
  • Had an obscure selection issue.  ListView (when virtualization is True), first time in, the CollectionView/ListView did not seem to know what the selectedItem was which caused a few issues. I added the above code to the ListView.Loaded event and selection seems to synchronize correctly now.

    I only seem to have this problem when virtualization is true.

    Tuesday, July 10, 2018 9:15 PM