Bulk loading in ObservableCollection.
Today, in Code Project, a poster asked a question about the best way to insert multiple items in ObservableCollection as a bulk insert. The poster wondered why it was taking so long to add records doing an Add for each item in the collection. Now, in several of the .NET collections, there’s an AddRange method that allows you to add multiple items in “one hit”, so why isn’t there one in ObservableCollection? Well, part of the reason seems to be that this goes outside what you would use an ObservableCollection for. In other words, it’s not aimed at adding multiple items, it’s aimed at monitoring small changes.
So, what makes ObservableCollection unsuitable for large scale inserts? Well, the primary reason lies in the fact that an Add operation fires off a CollectionChanged event – it’s this event that is contributing to a large part of the slowdown. Fortunately, there is a way to get round this limitation, and it lies in the wonderful world of inheritance.
The following class is based on an ObservableCollection, and adds a new method (AddRange) that adds the items in quickly by suppressing the CollectionChanged event until the load has finished. (It doesn’t implement a RemoveRange method, but it would follow a similar pattern). Simple tests showed that this ran 3 times faster than the ordinary methods.
public class RangeObservableCollection<T> : ObservableCollection<T>
{
private bool _suppressNotification = false;
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (!_suppressNotification)
base.OnCollectionChanged(e);
}
public void AddRange(IEnumerable<T> list)
{
if (list == null)
throw new ArgumentNullException("list");
_suppressNotification = true;
foreach (T item in list)
{
Add(item);
}
_suppressNotification = false;
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
Anyway, I hope this helps you out.




Nice idea, Pete.
Thanks very much. I’m glad you like it.
if the OnCollectionChanged using a different NotifyCollectionChangedEventArgs you can still observe the collection changeing. Using the constuctor of only passing NotifyCollectionChangeAction.Reset will not allow listeners to observe changes.
I suggest using
NotifyCollectionChangedEventArgs args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, list);
OnCollectionChanged(args);
And then for removal use .Remove
Now this is what I came here for tonight …
cut-paste-thanks.
Colin E.
Dude… you are awesome. Thanks so much.
Super! Thanks!
My datagrid 50*4 is binding on ObservableCollection. Changes occur frequently and over and over.
I used OnCollectionChanged, and saw a heavy load on the CPU. I tried use OnCollectionChanged from this topic, and saw a same heavy load on the CPU.
I did not understand the reason. I tried use OnPropertyChanged, and heavy load on the CPU disappeared.
To understand what is the reason I tried to modify the elements (not Clear and Add), but used the event OnCollectionChanged, which is called once, after all the changes. I get same – a heavy load on the CPU. So, I think, OnCollectionChanged – very slowly. Even if you do not use to redraw the elements, its use require much more CPU resourses…
Perfect… just saw a performance bottleneck completely vanish. Thankyou!