Description
Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.
OnCollectionChanged
|
var oc = new ObservableCollection<int>();
oc.CollectionChanged += OnCollectionChanged;
oc.Add(1);
oc.Add(9);
oc[0] = 2;
oc.Move(0, 1); // move item at index 0 to index 1
oc.RemoveAt(0);
oc.Clear();
private static void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
// sender: ObservableCollection
// e.Action : Add
// e.NewItems: ReadOnlyList<int>() { 1 }
// e.Action : Replace
// e.OldItems: ReadOnlyList<int>() { 1 }
// e.NewItems: ReadOnlyList<int>() { 2 }
// e.Action : Move
// e.OldItems: ReadOnlyList<int>() { 2 }
// e.NewItems: ReadOnlyList<int>() { 2 }
// e.Action : Remove
// e.OldItems: ReadOnlyList<int>() { 2 }
// Clear
// e.Action : Reset
}
|
Listen of item changes
|
var oc = new ObservableCollection<Item>();
oc.CollectionChanged += OnCollectionChanged;
oc.Add(new Item { Name = "One" });
oc[0].Name = "One+";
private static void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
RegisterItemPropertyChanged(e.NewItems);
break;
case NotifyCollectionChangedAction.Remove:
UnRegisterItemPropertyChanged(e.OldItems);
break;
case NotifyCollectionChangedAction.Replace:
UnRegisterItemPropertyChanged(e.OldItems);
RegisterItemPropertyChanged(e.NewItems);
break;
default:
break;
}
}
private static void RegisterItemPropertyChanged(IList newItems)
{
foreach (INotifyPropertyChanged item in newItems)
{
if (item != null)
{
item.PropertyChanged += new PropertyChangedEventHandler(ItemPropertyChanged);
}
}
}
private static void UnRegisterItemPropertyChanged(IList oldItems)
{
foreach (INotifyPropertyChanged item in oldItems)
{
if (item != null)
{
item.PropertyChanged -= new PropertyChangedEventHandler(ItemPropertyChanged);
}
}
}
private static void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
// sender: Item
// e.PropertyName: Name
}
class Item : INotifyPropertyChanged
{
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged("Name");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
|
Advanced ObservableCollection
- Send only 1 CollectionChanged event while adding multiple elements at the same time, instead of sending 1 CollectionChanged event per item added.
- Send only 1 CollectionChanged event while resseting the whole collection, instead of sending 1 CollectionChanged event for clear/reset and one for each item added.
ResettableObservableCollection.cs
|
public sealed class AdvancedObservableCollection<T> : ObservableCollection<T>
{
private bool raiseCollectionChangedEvent = true;
public void AddRange(IEnumerable<T> items)
{
try
{
this.raiseCollectionChangedEvent = false;
CollectionExtensions.AddRange(this, items);
this.OnPropertyChanged(new PropertyChangedEventArgs("Count"));
this.OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
base.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
finally
{
this.raiseCollectionChangedEvent = true;
}
}
public void Reset(IEnumerable<T> items)
{
try
{
this.raiseCollectionChangedEvent = false;
this.ClearItems();
// protected override void ClearItems()
// {
// this.CheckReentrancy();
// base.ClearItems();
// this.OnPropertyChanged("Count");
// this.OnPropertyChanged("Item[]");
// this.OnCollectionReset();
// }
// private void OnCollectionReset() => this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
CollectionExtensions.AddRange(this, items);
base.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
finally
{
this.raiseCollectionChangedEvent = true;
}
}
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (this.raiseCollectionChangedEvent)
{
base.OnCollectionChanged(e);
}
}
}
|