gpt4 book ai didi

c# - 可观察集合 : calling OnCollectionChanged with multiple new items

转载 作者:可可西里 更新时间:2023-11-01 09:10:38 25 4
gpt4 key购买 nike

请注意,我正在尝试使用 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));
}
}

正在 throw 集合添加事件指的是不属于集合的项目

这似乎是 BCL 中的错误?

我可以逐步查看并在调用 OnCollectionChanged 之前看到新项目已添加到 this.Items

刚刚有了一个惊人的发现。这些方法都不适合我(flush、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).. 没有什么不同。

最佳答案

您可以像这样为 ObservableCollection 实现 AddRange(),如图所示 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));
}
}

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

更新 2:添加了在 OnCollectionChanged() 的覆盖实现中引发覆盖的 CollectionChanged 事件的修复。

关于c# - 可观察集合 : calling OnCollectionChanged with multiple new items,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3300845/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com