自定义可观察集合与 AddRange 和 NotifyCollectionChangedAction.Add 不起作用
本文关键字:NotifyCollectionChangedAction Add 不起作用 AddRange 观察 集合 自定义 | 更新日期: 2023-09-27 18:32:44
我已经实现了一个 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
以便我可以观察更改。
谁能纠正我?
如果您使用内部IList<T>
添加项目,它不会像使用 Add
方法那样通知所有事件,
Add
方法的工作方式如下:
- 检查重入
- 插入项
- OnPropertyChanged("Count");
- OnPropertyChanged("Item[]");
- OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index);
因此,如果您跳过 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);
}