I have something here that is really catching me off guard.
I have an ObservableCollection of T that is filled with items. I also have an event handler attached to t
I tackled this one in a slightly different manner as I wanted to register to one event and handle all additions and removals in the event handler. I started off overriding the collection changed event and redirecting reset actions to removal actions with a list of items. This all went wrong as I was using the observable collection as an items source for a collection view and got "Range actions not supported".
I finally created a new event called CollectionChangedRange which acts in the manner I expected the inbuilt version to act.
I can't imagine why this limitation would be allowed and hope that this post at least stops others from going down the dead end that I did.
///
/// An observable collection with support for addrange and clear
///
///
[Serializable]
[TypeConverter(typeof(ExpandableObjectConverter))]
public class ObservableCollectionRange : ObservableCollection
{
private bool _addingRange;
[field: NonSerialized]
public event NotifyCollectionChangedEventHandler CollectionChangedRange;
protected virtual void OnCollectionChangedRange(NotifyCollectionChangedEventArgs e)
{
if ((CollectionChangedRange == null) || _addingRange) return;
using (BlockReentrancy())
{
CollectionChangedRange(this, e);
}
}
public void AddRange(IEnumerable collection)
{
CheckReentrancy();
var newItems = new List();
if ((collection == null) || (Items == null)) return;
using (var enumerator = collection.GetEnumerator())
{
while (enumerator.MoveNext())
{
_addingRange = true;
Add(enumerator.Current);
_addingRange = false;
newItems.Add(enumerator.Current);
}
}
OnCollectionChangedRange(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, newItems));
}
protected override void ClearItems()
{
CheckReentrancy();
var oldItems = new List(this);
base.ClearItems();
OnCollectionChangedRange(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, oldItems));
}
protected override void InsertItem(int index, T item)
{
CheckReentrancy();
base.InsertItem(index, item);
OnCollectionChangedRange(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
}
protected override void MoveItem(int oldIndex, int newIndex)
{
CheckReentrancy();
var item = base[oldIndex];
base.MoveItem(oldIndex, newIndex);
OnCollectionChangedRange(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, item, newIndex, oldIndex));
}
protected override void RemoveItem(int index)
{
CheckReentrancy();
var item = base[index];
base.RemoveItem(index);
OnCollectionChangedRange(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index));
}
protected override void SetItem(int index, T item)
{
CheckReentrancy();
var oldItem = base[index];
base.SetItem(index, item);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, oldItem, item, index));
}
}
///
/// A read only observable collection with support for addrange and clear
///
///
[Serializable]
[TypeConverter(typeof(ExpandableObjectConverter))]
public class ReadOnlyObservableCollectionRange : ReadOnlyObservableCollection
{
[field: NonSerialized]
public event NotifyCollectionChangedEventHandler CollectionChangedRange;
public ReadOnlyObservableCollectionRange(ObservableCollectionRange list) : base(list)
{
list.CollectionChangedRange += HandleCollectionChangedRange;
}
private void HandleCollectionChangedRange(object sender, NotifyCollectionChangedEventArgs e)
{
OnCollectionChangedRange(e);
}
protected virtual void OnCollectionChangedRange(NotifyCollectionChangedEventArgs args)
{
if (CollectionChangedRange != null)
{
CollectionChangedRange(this, args);
}
}
}