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 had the same issue, and this was my solution. It seems to work. Does anyone see any potential problems with this approach?
// overriden so that we can call GetInvocationList
public override event NotifyCollectionChangedEventHandler CollectionChanged;
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
NotifyCollectionChangedEventHandler collectionChanged = CollectionChanged;
if (collectionChanged != null)
{
lock (collectionChanged)
{
foreach (NotifyCollectionChangedEventHandler handler in collectionChanged.GetInvocationList())
{
try
{
handler(this, e);
}
catch (NotSupportedException ex)
{
// this will occur if this collection is used as an ItemsControl.ItemsSource
if (ex.Message == "Range actions are not supported.")
{
handler(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
else
{
throw ex;
}
}
}
}
}
}
Here are some other useful methods in my class:
public void SetItems(IEnumerable newItems)
{
Items.Clear();
foreach (T newItem in newItems)
{
Items.Add(newItem);
}
NotifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public void AddRange(IEnumerable newItems)
{
int index = Count;
foreach (T item in newItems)
{
Items.Add(item);
}
NotifyCollectionChangedEventArgs e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, new List(newItems), index);
NotifyCollectionChanged(e);
}
public void RemoveRange(int startingIndex, int count)
{
IList oldItems = new List();
for (int i = 0; i < count; i++)
{
oldItems.Add(Items[startingIndex]);
Items.RemoveAt(startingIndex);
}
NotifyCollectionChangedEventArgs e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, new List(oldItems), startingIndex);
NotifyCollectionChanged(e);
}
// this needs to be overridden to avoid raising a NotifyCollectionChangedEvent with NotifyCollectionChangedAction.Reset, which our other lists don't support
new public void Clear()
{
RemoveRange(0, Count);
}
public void RemoveWhere(Func criterion)
{
List removedItems = null;
int startingIndex = default(int);
int contiguousCount = default(int);
for (int i = 0; i < Count; i++)
{
T item = Items[i];
if (criterion(item))
{
if (removedItems == null)
{
removedItems = new List();
startingIndex = i;
contiguousCount = 0;
}
Items.RemoveAt(i);
removedItems.Add(item);
contiguousCount++;
}
else if (removedItems != null)
{
NotifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, removedItems, startingIndex));
removedItems = null;
i = startingIndex;
}
}
if (removedItems != null)
{
NotifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, removedItems, startingIndex));
}
}
private void NotifyCollectionChanged(NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(new PropertyChangedEventArgs("Count"));
OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
OnCollectionChanged(e);
}