的ObservableCollection:调用OnCollectionChanged有多个新项目 [英] ObservableCollection : calling OnCollectionChanged with multiple new items

查看:519
本文介绍了的ObservableCollection:调用OnCollectionChanged有多个新项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请注意,我试图用NotifyCollectionChangedAction.Add操作而不是.reset段。后者的工作,但它是不是很有效的大集合。

please note that I am trying to use NotifyCollectionChangedAction.Add action instead of .Reset. the latter does work, but it is not very efficient with large collections.

所以我子类的ObservableCollection:

so i subclassed ObservableCollection:

public class SuspendableObservableCollection<T> : ObservableCollection<T>

由于某种原因,这个code:

for some reason, this code:

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));
        }
    }

是扔
集合添加的事件是指不属于集合项目

is throwing A collection Add event refers to item that does not belong to collection

这似乎是BCL的错误吗?

this appears to be a bug in BCL ?

我可以逐步并在调用OnCollectionChanged新的项目添加到this.Items见

I can step through and see prior to calling OnCollectionChanged that new items are added to this.Items

WOW

刚刚作出了一个惊人的发现。这些方法都没有工作对我来说(冲洗,的AddRange),因为这个错误似乎是触发仅当此集合绑定到我列表视图!

just made a staggering discovery. None of these approaches worked for me (flush, addrange), because the error appears to be triggered ONLY if this collection is bound to my 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段)。

In conclusion, ObservableCollection does support adding incremental lists, but a ListView doesn't. Andyp figured out a workaround to make it work with CollectionView below, but since .Refresh() is called, that is no different than just calling OnCollectionChanged( .Reset )..

推荐答案

您可以像这样的ObservableCollection实现的AddRange()如图所示的这里

you can implement AddRange() for the ObservableCollection like this as shown here:

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));
    }
}

更新:绑定的ListBox我看到一个InvalidOperationException太后(同样的消息你看到的)。根据本<一href=\"http://geekswithblogs.net/NewThingsILearned/archive/2008/01/16/listcollectionviewcollectionview-doesnt-support-notifycollectionchanged-with-multiple-items.aspx\"相对=nofollow>文章,那是因为的CollectionView不支持范围的行动。幸运的是,文章还提供了一个解决方案(虽然感觉有点黑客十岁上下)。

UPDATE: After binding to ListBox I was seeing an InvalidOperationException too (same message you were seeing). According to this article that's because CollectionView doesn't support range actions. Luckily the article also supplies a solution (although it feels a little "hack-ish").

更新2:增加引发的重写实施OnCollectionChanged的覆盖CollectionChanged事件(修复)

UPDATE 2: Added a fix that raises the overridden CollectionChanged event in the overridden implementation of OnCollectionChanged().

这篇关于的ObservableCollection:调用OnCollectionChanged有多个新项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆