ObservableCollection 不支持 AddRange 方法,因此我会收到添加的每个项目的通知,除了 INotifyCollectionChanging 之外?
I want to be able to add a range and get updated for the entire bulk.
I also want to be able to cancel the action before it's done (i.e. collection changing besides the 'changed').
Related Q
Which .Net collection for adding multiple objects at once and getting notified?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
这是一个简单的可观察集合,基于这篇文章,在 AddRange 方法结束时发出通知
https://peteohanlon.wordpress.com/2008/10 /22/bulk-loading-in-observablecollection/
它也是异步的并且可以跨线程修改,基于这篇文章https://thomaslevesque.com/2009/04/17/wpf-binding-to-an-asynchronous-collection/
this a simple observablecollection that notifies at the end of AddRange method, based on this post
https://peteohanlon.wordpress.com/2008/10/22/bulk-loading-in-observablecollection/
it is also asynchronous and modifiable across threads, based on this post https://thomaslevesque.com/2009/04/17/wpf-binding-to-an-asynchronous-collection/
这里是有关集合更改和 UI 问题的一些额外帮助:
Here is some additional help for collection changed and UI issues:
ObservableRangeCollection 应该通过测试,就像
我们
在使用控件时得到的那样。
我没有看到理想的解决方案,但 NotifyCollectionChangedAction.Reset 而不是添加/删除部分解决了问题。 请参阅 http://blogs.msdn。 com/b/nathannesbit/archive/2009/04/20/addrange-and-observablecollection.aspx 正如 net_prog 提到的
ObservableRangeCollection should pass a test like
otherwise we get
while using with a control.
I do not see an ideal solution, but NotifyCollectionChangedAction.Reset instead of Add/Remove partially solve the problem. See http://blogs.msdn.com/b/nathannesbit/archive/2009/04/20/addrange-and-observablecollection.aspx as was mentioned by net_prog
这是对已接受答案的修改,以提供更多功能。
RangeCollection.cs:
事件类:
注意:我没有在基本方法中手动引发
OnCollectionChanged
,因为它似乎只能使用Reset 创建
行动。 如果您尝试使用CollectionChangedEventArgs
Reset
引发OnCollectionChanged
以进行单个项目更改,您的项目控件将出现闪烁,这是您想要避免的情况。Here's a modification of the accepted answer to provide more functionality.
RangeCollection.cs:
Events Classes:
Note: I did not manually raise
OnCollectionChanged
in the base methods because it appears only to be possible to create aCollectionChangedEventArgs
using theReset
action. If you try to raiseOnCollectionChanged
usingReset
for a single item change, your items control will appear to flicker, which is something you want to avoid.您还可以使用此代码来扩展 ObservableCollection:
那么您不需要更改现有代码中的类。
You can also use this code to extend ObservableCollection:
Then you don't need to change class in existing code.
请参阅更新和优化的C# 7版本。 我不想删除 VB.NET 版本,所以我只是将其发布在单独的答案中。
转到更新版本
似乎不支持,我自己实现的,仅供参考,希望它有帮助:
我更新了VB版本,从现在开始,它会在更改集合之前引发一个事件,这样您就可以后悔(与
DataGrid
、ListView
等一起使用时很有用,您可以显示“Are您确定”向用户确认),更新的 VB 版本位于此消息的底部。请接受我的歉意,屏幕太窄,无法包含我的代码,我也不喜欢它。
VB.NET:
C#:
更新 - 可观察范围集合,带有集合更改通知
Please refer to the updated and optimized C# 7 version. I didn't want to remove the VB.NET version so I just posted it in a separate answer.
Go to updated version
Seems it's not supported, I implemented by myself, FYI, hope it to be helpful:
I updated the VB version and from now on it raises an event before changing the collection so you can regret (useful when using with
DataGrid
,ListView
and many more, that you can show an "Are you sure" confirmation to the user), the updated VB version is in the bottom of this message.Please accept my apology that the screen is too narrow to contain my code, I don't like it either.
VB.NET:
C#:
Update - Observable range collection with collection changing notification
首先,请对 API 请求进行投票和评论 在 .NET 存储库上。
这是我的
ObservableRangeCollection
的优化版本(James Montemagno 的 一个)。它执行速度非常快,旨在尽可能重用现有元素并避免不必要的事件,或者在可能的情况下将它们批处理为一个。
ReplaceRange
方法通过适当的索引替换/删除/添加所需的元素并对可能的事件进行批处理。在 Xamarin.Forms UI 上进行了测试,对于非常频繁地更新大型集合(每秒 5-7 次更新),结果很好。
笔记:
由于 WPF 不习惯使用范围操作,因此在 WPF UI 相关工作中使用下面的
ObservableRangeCollection
时,它会抛出NotSupportedException
,例如将其绑定到ListBox
等(如果未绑定到 UI,您仍然可以使用ObservableRangeCollection
)。但是,您可以使用
WpfObservableRangeCollection
解决方法。真正的解决方案是创建一个知道如何处理范围操作的 CollectionView,但我仍然没有时间来实现它。
RAW 代码 - 作为 Raw 打开,然后执行 Ctrl< /kbd>+A 选择全部,然后 Ctrl+C 进行复制。
First of all, please vote and comment on the API request on the .NET repo.
Here's my optimized version of the
ObservableRangeCollection
(optimized version of James Montemagno's one).It performs very fast and is meant to reuse existing elements when possible and avoid unnecessary events, or batching them into one, when possible.
The
ReplaceRange
method replaces/removes/adds the required elements by the appropriate indices and batches the possible events.Tested on Xamarin.Forms UI with great results for very frequent updates to the large collection (5-7 updates per second).
Note:
Since WPF is not accustomed to work with range operations, it will throw a
NotSupportedException
, when using theObservableRangeCollection
from below in WPF UI-related work, such as binding it to aListBox
etc. (you can still use theObservableRangeCollection<T>
if not bound to UI).However you can use the
WpfObservableRangeCollection<T>
workaround.The real solution would be creating a
CollectionView
that knows how to deal with range operations, but I still didn't have the time to implement this.RAW Code - open as Raw, then do Ctrl+A to select all, then Ctrl+C to copy.
我认为 AddRange 的实现方式更好:
它可以为您保存列表副本。 另外,如果您想进行微优化,您可以添加最多 N 个项目,如果添加的项目超过 N 个,则进行重置。
I think AddRange is better implemented like so:
It saves you a list copy. Also if you want to micro-optimise you could do adds for up to N items and if more than N items where added do a reset.
将 UI 绑定到自定义集合时必须小心 - 默认 CollectionView 类仅支持单个项目通知。
You will have to be careful binding the UI to your custom collection -- the Default CollectionView class only supports single notification of items.
需要
OnPropertyChanged("Count")
和OnPropertyChanged("Item[]")
调用的证明,以便按照ObservableCollection
进行操作。 注意,如果不打扰我不知道后果是什么!下面是一个测试方法,它显示正常可观察集合中的每个添加都有两个 PropertyChange 事件。 一种用于
“Count”
,另一种用于“Item[]”
。@Shimmy,交换您的集合的标准并更改为添加范围,您将获得零 PropertyChanges。 请注意,集合更改确实可以正常工作,但并不完全像 ObservableCollection 那样。 因此,对 shimmy 集合的测试如下所示:
仅供参考,这里是来自 ObservableCollection 的 InsertItem(也由 Add 调用)的代码:
Proof of need for
OnPropertyChanged("Count")
andOnPropertyChanged("Item[]")
calls in order to behave as perObservableCollection
. Note that I don't know what the consequences are if you don't bother!Here is a test method that shows that there are two PropertyChange events for each add in a normal observable collection. One for
"Count"
and one for"Item[]"
.@Shimmy , swap the standard for your collection and change to an add range and you will get zero PropertyChanges. Note that collection change does work fine, but not doing exactly what ObservableCollection does. So Test for shimmy collection looks like this:
FYI here is code from InsertItem (also called by Add) from ObservableCollection:
由于可能需要对 ObservableCollection 执行许多操作,例如先清除,然后添加范围,然后为组合框插入“全部”项,我最终得到以下解决方案:
以及如何使用它的示例:
仅调用重置通知执行完成处理底层列表后一次。
As there might be a number of operations to do on an ObservableCollection for example Clear first then AddRange and then insert "All" item for a ComboBox I ended up with folowing solution:
And example how to use it:
The Reset notification will be called only once after Execute is finished processing the underlying list.
C# 总结了后代。
更多阅读:http://blogs. msdn.com/b/nathannesbit/archive/2009/04/20/addrange-and-observablecollection.aspx
The C# summarized descendant.
More reading: http://blogs.msdn.com/b/nathannesbit/archive/2009/04/20/addrange-and-observablecollection.aspx
是的,添加您自己的自定义可观察集合就足够公平了。 不要忘记引发适当的事件,无论 UI 目前是否使用它;)您必须引发“Item[]”属性的属性更改通知(WPF 侧控件和绑定控件需要)以及 NotifyCollectionChangedEventArgs添加了一组项目(您的范围)。
我已经做过这样的事情(以及排序支持和其他一些东西)并且演示层和代码隐藏层都没有问题。
Yes, adding your own Custom Observable Collection would be fair enough. Don't forget to raise appropriate events regardless whether it is used by UI for the moment or not ;) You will have to raise property change notification for "Item[]" property (required by WPF side and bound controls) as well as NotifyCollectionChangedEventArgs with a set of items added (your range).
I've did such things (as well as sorting support and some other stuff) and had no problems with both Presentation and Code Behind layers.