开发者

WPF data virtualization issues

I need to display about few million items in WPF ListBox (I am aware how bad idea this is, but I have to do it this way). New items are arriving very quickly, thousands per second, but apart from that no changes are made to the list: items are never removed or modified. I need the LisBox control to be refreshed at least once per second.

I understand that I get UI virtualization "for free" in WPF (I'm using VirtualizedStackPanel in Recycle mode and deferred scrolling), but I have to virtualize the data. I'm completely new to WPF so I tried to leverage the best existing solution that I found. It works but flickers each time the count is refr开发者_如何学编程eshed, and SelectedItem is lost on each reload (I assume this is because it fires the CollectionChanged of "Reset" type that reloads the whole collection). I tried to use "Add" event instead of "Reset" but it requires list of items that were actually added to the collection and it doesn't really make any sense to fetch several thousand of objects per second just to pass them to the event and throw them away because they're virtualized anyway. I also tried to just fire PropertyChanged for Count property, so that the ListBox would update it's index range/adjust scrollbar, bizzare things started to happen: the scrollbar would adjust to the new count, though list items wouldn't display and still plenty of flickering.

In other words: how do I inform the ListBox control that N new items were added to the bound collection so that the ListBox will just adjust the scrollbar range (and won't ask me for the added items until they're actually displayed).

I'm using .NET 4.0 and Caliburn.Micro in this project but I doubt that this will affect potential solutions.


I had a similar situation wherein my cached list of objects (in millions) were bound to multiple ListBoxes across application (loaded on various pages), and when a cached item would be added, deleted or edited I had to maintain the selection and update the changes across the application without scroll or selection flicker.

I implemented it this way...

  1. I got a thread safe ObservableCollection called FastObservableCollection ... Updating an ObservableCollection in a separate thread

  2. I added support for AddRange() in the above FastObservaleCollection for bulk inserts without CollectionChanged Notifications. CollectionChanged notification would fire ONLY once for the last item added from the bulk.... http://peteohanlon.wordpress.com/2008/10/22/bulk-loading-in-observablecollection/

  3. Used Thread safe CollectionViews. You can customize a collection view and dispatch the event of SourceCollection.CollectionChanged on correct thread by raising a custom 'Refreshed' event.

This link provides the guide for the dispatched collection changed notification... Where do I get a thread-safe CollectionView?

  1. I changed my ListBoxes to use SelectedValue bindings instead of SelectedItem binding and made sure that SelectedValue is a primitive type (value type). This maintains the selection by value.

  2. I would call ListBox.SelectedValue's binding expression's UpdateSource() and UpdateTarget() when ListBox ItemsSource i.e. a custom refresh event raised from the CollectionView is handled through an attached behavior.

Now it works like charm without any filckering and maintains selection as well.


you need to create a custom collection that implements the non-generic IList interface as well as the generic IList. If you do this then a listbox control wont enumerate the collection but use the this[] interface which give you an opportunity to load rows in a paged style automatically when the user scrolls.

Here is a similar solution I posted on my blog: http://www.deanchalk.me.uk/post/WPF-e28093-DataContext-Virtualization-With-Paged-Services.aspx

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜