I have a WPF application that uses MVVM data bindings. I am adding items to an ObservableCollection<...>
and quite many of them indeed.
Now I am wondering that every time I add one to the collection, does it instantly fire the event and cause unnecessary overhead? If so, can I somehow temporarily disable the event notifications and manually fire it once at the end of my code so that if I add 10k items, it gets only fired once, rather than 10k times?
Update: I tried having this class:
using System;
using System.Linq;
using System.Collections.Specialized;
using System.Collections.Generic;
namespace MyProject
{
/// <summary>
/// Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.
/// </summary>
/// <typeparam name="T"></typeparam>
public class ObservableCollection<T> : System.Collections.ObjectModel.ObservableCollection<T>
{
/// <summary>
/// Adds the elements of the specified collection to the end of the ObservableCollection(Of T).
/// </summary>
public void AddRange(IEnumerable<T> collection)
{
foreach (var i in collection) Items.Add(i);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, collection.ToList()));
}
/// <summary>
/// Removes the first occurence of each item in the specified collection from ObservableCollection(Of T).
/// </summary>
public void RemoveRange(IEnumerable<T> collection)
{
foreach (var i in collection) Items.Remove(i);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, collection.ToList()));
}
/// <summary>
/// Clears the current collection and replaces it with the specified item.
/// </summary>
public void Replace(T item)
{
ReplaceRange(new T[] { item });
}
/// <summary>
/// Clears the current collection and replaces it with the specified collection.
/// </summary>
public void ReplaceRange(IEnumerable<T> collection)
{
List<T> old = new List<T>(Items);
Items.Clear();
foreach (var i in collection) Items.Add(i);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, collection.ToList()));
}
/// <summary>
/// Initializes a new instance of the System.Collections.ObjectModel.ObservableCollection(Of T) class.
/// </summary>
public ObservableCollection() : base() { }
/// <summary>
/// Initializes a new instance of the System.Collections.ObjectModel.ObservableCollection(Of T) class that contains elements copied from the specified collection.
/// </summary>
/// <param name="collection">collection: The collection from which the elements are copied.</param>
/// <exception cref="System.ArgumentNullException">The collection parameter cannot be null.</exception>
public ObservableCollection(IEnumerable<T> collection) : base(collection) { }
}
}
I get this error now:
Additional information: Range actions are not supported.
The error comes here:
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, collection.ToList()));
Data binding is a mechanism in WPF applications that provides a simple and easy way for Windows Runtime apps to display and interact with data. In this mechanism, the management of data is entirely separated from the way data. Data binding allows the flow of data between UI elements and data object on user interface.
Two way binding is used when we want to update some controls property when some other related controls property change and when source property change the actual control also updates its property.
WPF binding offers four types of Binding.
WPF data binding supports data in the form of CLR objects and XML. To provide some examples, your binding source may be a UIElement, any list object, a CLR object that is associated with ADO.NET data or Web Services, or an XmlNode that contains your XML data.
This extension of ObservableCollection solves the problem easily.
It exposes a public SupressNotification property to allow the user to control when CollectionChanged notification will be suppressed.
It does not offer range insertion/deletion, but if CollectionChanged notification is suppressed, the need to do range operation on the collection diminishes in most of the cases.
This implementation substitutes all suppressed notifications with a Reset notification. This is logically sensible. When the user suppresses the notification, do bulk changes and then re-enable it, it should appropriate to send a Resent notification.
public class ObservableCollectionEx<T> : ObservableCollection<T>
{
private bool _notificationSupressed = false;
private bool _supressNotification = false;
public bool SupressNotification
{
get
{
return _supressNotification;
}
set
{
_supressNotification = value;
if (_supressNotification == false && _notificationSupressed)
{
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
_notificationSupressed = false;
}
}
}
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (SupressNotification)
{
_notificationSupressed = true;
return;
}
base.OnCollectionChanged(e);
}
}
A very quick and easy way is to subclass ObservableCollection and suspend notifications when AddRange is called. See the following blog post for clarification.
There is a kind of "tricky" way, but pretty accurate, in my opinion, to achieve this.
Is to write you own ObservableCollection
and implement AddRange
handling.
In this way you can add all your 10k elements into some "holder collection" and after, one time you finished, use AddRange
of your ObservableColleciton
to do that.
More on this you can find on this link:
ObservableCollection Doesn't support AddRange method....
or this one too
AddRange and ObservableCollection
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With