使用AddRange& amp;定制Observable Collection NotifyCollectionChangedAction.Add不起作用

时间:2013-09-25 20:13:43

标签: c# wpf

我已经实现了一个ObservableCollection来支持批量添加,如下所示并绑定到WPF UI -

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

                _suspendCollectionChangeNotification = true;
                var newItems = new List<T>();

                foreach (T item in list)
                {
                    if (!Contains(item))
                    {
                        Add(item);
                        newItems.Add(item);
                    }
                }
                _suspendCollectionChangeNotification = false;

                var arg = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, newItems);
                OnCollectionChanged(arg);  //NotifyCollectionChangedAction.Reset works!!!
            }
        }
    }

    public override event NotifyCollectionChangedEventHandler CollectionChanged;

            protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
            {
                NotifyCollectionChanged(e);
            }

            internal void NotifyCollectionChanged(NotifyCollectionChangedEventArgs e)
            {
                if (IsCollectionChangeSuspended)
                {
                    return;
                }

                NotifyCollectionChangedEventHandler handler = CollectionChanged;
                if (handler != null)
                {
                    if (Application.Current != null && !Application.Current.Dispatcher.CheckAccess())
                    {
                        Application.Current.Dispatcher.Invoke(DispatcherPriority.DataBind,handler, this, e);
                    }
                    else
                    {
                        handler(this, e);
                    }
                }
            }

    private bool IsCollectionChangeSuspended
    {
        get { return _suspendCollectionChangeNotification; }
    }

我收到此错误 - {“收集已修改;枚举操作可能无法执行。”}

但是,如果我将NotifyCollectionChangedAction.Add更改为NotifyCollectionChangedAction.Reset并且未传递任何更改的列表,则它会正确绑定到UI。但是,我想使用NotifyCollectionChangedAction.Add,以便我可以观察到这些变化。

任何人都可以纠正我吗?

1 个答案:

答案 0 :(得分:2)

如果您使用内部IList<T>添加项目,则不会通知所有事件,例如使用Add方法,

Add方法的工作原理如下:

  1. CheckReentrancy
  2. InsertItem
  3. OnPropertyChanged( “计数”);
  4. OnPropertyChanged( “项目[]”);
  5. OnCollectionChanged(NotifyCollectionChangedAction.Add,item,index);
  6. 因此,如果您跳过Add方法并将项目直接添加到基础集合中,您可能会想到这一点。

    示例:(未经测试)

    public void AddRange(IEnumerable<T> rangeItems)
    {
        foreach (var item in rangeItems)
        {
             Items.Add(item);
        }
    
                base.OnPropertyChanged(new PropertyChangedEventArgs("Count"));
                base.OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
                var arg = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, rangeItems);
                OnCollectionChanged(arg);
    }