请注意,我正在尝试使用NotifyCollectionChangedAction.Add操作而不是.Reset。后者确实可以工作,但是对于大型馆藏来说效率不高。

所以我把ObservableCollection子类化了:

public class SuspendableObservableCollection<T> : ObservableCollection<T>

由于某种原因,此代码:
private List<T> _cachedItems;
...

    public void FlushCache() {
        if (_cachedItems.Count > 0) {

        foreach (var item in _cachedItems)
            Items.Add(item);

        OnCollectionChanged(new NotifyCollectionChangedEventArgs(
            NotifyCollectionChangedAction.Add, (IList<T>)_cachedItems));
        }
    }


集合添加事件引用不属于集合的项目

这似乎是BCL中的错误?

我可以逐步了解并在调用OnCollectionChanged之前将新项目添加到this.Items中。

WOW

刚刚做了一个惊人的发现。这些方法对我都不起作用(刷新,addrange),因为仅当此集合绑定(bind)到我的Listview时,才会出现该错误!
TestObservableCollection<Trade> testCollection = new TestObservableCollection<Trade>();
List<Trade> testTrades = new List<Trade>();

for (int i = 0; i < 200000; i++)
    testTrades.Add(t);

testCollection.AddRange(testTrades); // no problems here..
_trades.AddRange(testTrades); // this one is bound to ListView .. BOOOM!!!

总之,ObservableCollection确实支持添加增量列表,但ListView不支持。 Andyp找到了一种解决方法,使其可以与下面的CollectionView一起使用,但是由于调用了.Refresh(),因此与仅调用OnCollectionChanged(.Reset)没有什么不同。

最佳答案

您可以像here所示为ObservableCollection实现AddRange():

public class RangeObservableCollection<T> : ObservableCollection<T>
{
    private bool _SuppressNotification;

    public override event NotifyCollectionChangedEventHandler CollectionChanged;

    protected virtual void OnCollectionChangedMultiItem(
        NotifyCollectionChangedEventArgs e)
    {
        NotifyCollectionChangedEventHandler handlers = this.CollectionChanged;
        if (handlers != null)
        {
            foreach (NotifyCollectionChangedEventHandler handler in
                handlers.GetInvocationList())
            {
                if (handler.Target is CollectionView)
                    ((CollectionView)handler.Target).Refresh();
                else
                    handler(this, e);
            }
        }
    }

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        if (!_SuppressNotification)
        {
            base.OnCollectionChanged(e);
            if (CollectionChanged != null)
                CollectionChanged.Invoke(this, e);
        }
    }

    public void AddRange(IEnumerable<T> list)
    {
        if (list == null)
            throw new ArgumentNullException("list");

        _SuppressNotification = true;

        foreach (T item in list)
        {
            Add(item);
        }
        _SuppressNotification = false;

        OnCollectionChangedMultiItem(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, list));
    }
}

更新:绑定(bind)到ListBox后,我也看到了InvalidOperationException(与您看到的消息相同)。根据这个article,这是因为CollectionView不支持范围 Action 。幸运的是,该文章还提供了一种解决方案(尽管感觉有点“破烂”)。

更新2:添加了一个修补程序,该修补程序在OnCollectionChanged()的重写实现中引发了被重写的CollectionChanged事件。

09-11 04:54