-
Notifications
You must be signed in to change notification settings - Fork 5
Issue of Refreshes while selecting items
Refreshes while selecting an item break the data virtualization (DV)!
Preferably don't use selection. If you have to, workaround by binding the SelectedIndex
-Property of the used Selector
control to the SelectedIndex
-Property of the DV collection, respectively.
The standard ItemControls
of WPF wrap their ItemsSource
in a inheritance descendant of CollectionView
. In case of an ItemsSource
of type IList
the ListCollectionView
is use. It is exactly the type of CollectionView
which we are going for, because the ListCollectionView
is optimized to use the indexer of IList
(random access) and therefore enables data virtualization.
However, on refreshes it memorizes the selected item prior to the refresh and searches the whole list for it afterwards. If the same item isn't in the same spot anymore it'll search the whole list from first to last item until it finds the spot of the selected item in order to select its new position. This behavior breaks the data virtualization, because in the process a lot of items are forced to be loaded which are not relevant.
If you want the search of the previously selected item to not finish empty handed, you would need either to recycle the item objects between refreshes (not necessarily advised to) or override GetHashCode
/Equals
(shouldn't be necessarily required for DV). However, the searched item still could be positioned in a later part of the collection, hence forcing the DV to load a big part or (almost) everything. Still there also is the possibility that the previously selected item isn't present after the refresh anymore (for example it could have been deleted). Such a search will always load all data and be fruitless. This is a nightmare for applications which depend on a working data virtualization in order to be usable. You need to workaround this issue.
One workaround option integrated into the data virtualizing collection is the usage of their SelectedIndex
-Property. Before any Refresh it'll be set to -1 (which isn't a valid index) which effectively deselects the items. Bind that property to the SelectedIndex
-Property of the Selector control in order to automatically deselect and hence not break the data virtualization.
Another workaround option is to build your own workaround around the data virtualizing collection. Of course you could do something before and after you trigger the refresh, but be warned! I did try such workaround in the past myself. Even though you get more control you'll also introduce a lot of overhead and complexity to your code. So your own workaround should really be worth it.
The ItemsControl
s are working with the window collection of the sliding window not the whole virtualized backend. Because the window size should be efficiently processable at any time, even if the ListCollectionView
compares every item after a refresh, the current position and relatively narrow size of the window guarantee that only a small section of the backend is loaded. Hence the data virtualization is still kept intact.
However, if you don't recycle item objects nor override GetHashCode
/Equals
, the selected item will be deselected on a refresh, because the search for the selected item will fail.