Implement RemoveAll on AsyncObservableCollection

非 Y 不嫁゛ 提交于 2020-05-15 10:10:12

问题


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?


回答1:


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.



来源:https://stackoverflow.com/questions/47287326/implement-removeall-on-asyncobservablecollection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!