Reputation: 29
I'm trying to implement the RemoveAll
on AsyncObservableCollection
, this class was created for edit the collection on another thread, the structure is this:
public class AsyncObservableCollection<T> : ObservableCollection<T>
{
private readonly SynchronizationContext _synchronizationContext = SynchronizationContext.Current;
public AsyncObservableCollection()
{
}
public AsyncObservableCollection(IEnumerable<T> list)
: base(list)
{
}
private void ExecuteOnSyncContext(Action action)
{
if (SynchronizationContext.Current == _synchronizationContext)
{
action();
}
else
{
_synchronizationContext.Send(_ => action(), null);
}
}
protected override void InsertItem(int index, T item)
{
ExecuteOnSyncContext(() => base.InsertItem(index, item));
}
protected override void RemoveItem(int index)
{
ExecuteOnSyncContext(() => base.RemoveItem(index));
}
protected override void SetItem(int index, T item)
{
ExecuteOnSyncContext(() => base.SetItem(index, item));
}
protected override void MoveItem(int oldIndex, int newIndex)
{
ExecuteOnSyncContext(() => base.MoveItem(oldIndex, newIndex));
}
protected override void ClearItems()
{
ExecuteOnSyncContext(() => base.ClearItems());
}
public void RemoveAll(Predicate<T> predicate)
{
CheckReentrancy();
List<T> itemsToRemove = Items.Where(x => predicate(x)).ToList();
itemsToRemove.ForEach(item => Items.Remove(item));
OnPropertyChanged(new PropertyChangedEventArgs("Count"));
OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
actually the method working well if the collection is used on the main thread, but if I use on a different thread I get:
Not Supported Exception
on this line:
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
there is something that I can do for fix this?
Upvotes: 2
Views: 515
Reputation: 372
I am not really sure the purpose of this class and why you need to keep the current context, but anyways the solution to your problem is
public class ObservableCollectionAsync<T> : ObservableCollection<T>
{
public ObservableCollectionAsync()
{
BindingOperations.EnableCollectionSynchronization(this, _lock);
}
public ObservableCollectionAsync(List<T> list) : base(list)
{
BindingOperations.EnableCollectionSynchronization(this, _lock);
}
public ObservableCollectionAsync(IEnumerable<T> collection) : base(collection)
{
BindingOperations.EnableCollectionSynchronization(this, _lock);
}
private readonly SynchronizationContext _synchronizationContext = SynchronizationContext.Current;
private readonly object _lock = new object();
private void ExecuteOnSyncContext(Action action)
{
if (SynchronizationContext.Current == _synchronizationContext)
{
action();
}
else
{
_synchronizationContext.Send(_ => action(), null);
}
}
protected override void ClearItems()
{
ExecuteOnSyncContext(() => base.ClearItems());
}
protected override void InsertItem(int index, T item)
{
ExecuteOnSyncContext(() => base.InsertItem(index, item));
}
protected override void MoveItem(int oldIndex, int newIndex)
{
ExecuteOnSyncContext(() => base.MoveItem(oldIndex, newIndex));
}
protected override void RemoveItem(int index)
{
ExecuteOnSyncContext(() => base.RemoveItem(index));
}
protected override void SetItem(int index, T item)
{
ExecuteOnSyncContext(() => base.SetItem(index, item));
}
public void RemoveAll(Func<T,bool> predicate)
{
CheckReentrancy();
foreach (var item in this.Where(predicate).ToArray())
{
this.Remove(item);
}
}
But any of the other methods within the Observable Collection itself will not go through your "ExecuteOnSyncContext", so it may be better to just make it public and call it outside the class for the other methods.
Otherwise you'll need to build an Observable Collection using the ICollection interface.
Upvotes: 1