Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF: what's the most efficient/fast way of adding items to a ListView?

I need to display lots of rows in a grid added at a pretty high frequency (up to 10 rows per second in some cases) I chose ListView because I assume is the fastest grid control in WPF. (certainly a lot faster than GridView)

CPU utilization gets pretty high after couple hundred thousand items were added and they continue to come in. This is rather surprising, as ListView renders only the visible rows, so it should not matter how many are added in total.

My first approach was binding it to ObservableCollection but after a while, the CPU utilization goes up, and the whole Window get jittery.

Than i tried binding it to a regular List, which appears to be faster, however i do need to call the .Refresh() on the list often, which after a while slams the CPU as well.

Than i attempted subclassing ObservableCollection to chunk inserts hoping that batching them would improve performance/decrease cpu workload, but this approach appears to require calling CollectionView.Refresh which is the same as calling Reset() on the collection, and also ineficient when there are lots of items in the collection.

Clearing the observablecollection and than calling myListView.Items.Refresh() to bring it back down to 0 brings cpu usage back to the starting point.

Starting to run out of ideas here.. Again, my aim here, is to add/display lots of items and display 8 column grid, in the most performant manner.. ListView seems good, there just have to be some ways i could further tweak it..

UPDATE

after profiling, ObservableCollection 800k rows in the grid, the most cpu intensive work is done by :

  • (75%) System.Windows.Media.MediaContext.RenderMessageHandler(object resizedCompositionTarget)
  • (20%) ObservableCollection.OnCollectionChanged(NotifyCoolectionChanged..)

although depending on session those numbers vary greatly..

UPDATE 2 .. ok BindingList appears to be the clear winner here.

here are results (in ticks) side by side with 1 million rows each (and adding 10 items per second):

ObservableCollection: http://i.imgur.com/7ZoSv.png

BindingList http://i.imgur.com/jm5qF.png

you can see overall drop in CPU activity, and about half the ticks required to process the tree in Binding List case! My thanks to Akash for this great idea.

like image 768
Sonic Soul Avatar asked Jul 22 '10 02:07

Sonic Soul


1 Answers

Instead of using ObservableCollection I will suggest BindingList class, you can do something like this..

BindingList<string> list = new BindingList<string>();

list.AllowEdit = true;
list.AllowNew = true;
list.AllowRemove = true;

// set the list as items source
itemCollection.ItemsSource = list;

// add many items...

// disable UI updation
list.RaiseListChangedEvents = false;

for each(string s in MyCollection){
   list.Add(s);
}

// after all.. update the UI with following
list.RaiseListChangedEvents = true;
list.ResetBindings(); // this forces update of entire list

You can enable/disable updating even in batches, instead of adding everything at one shot, BindingList has been functioning better then ObservableCollection in all my UI, I wonder why everywhere people talk more about ObservableCollection when BindingList really superseds ObservableCollection.

like image 190
Akash Kava Avatar answered Oct 16 '22 02:10

Akash Kava