我有一个列表框,里面有一个嵌套的列表框。两者都将 ObservableCollections 作为其 ItemsSource 设置,内部 ListBox 的集合是外部 ListBox 对象的成员...
这些集合由从 Web 服务收集数据的 BackgroundWorker 填充。我必须从 ObservableCollection 更改为 AsyncObservableCollection,以便能够从工作人员代码中添加项目。 AsyncObservableCollection 代码来自此处: 让工作线程更新绑定到 ListCollectionView 的 ObservableCollection
我的问题是内部ListBox 不断显示重复的项目。如果它决定复制,它似乎总是会复制第一个项目。我不知道为什么会发生这种情况。通过附加到集合的 CollectionChanged 事件的事件侦听器,我发现每个项目都可以正常触发该事件一次。
你有什么想法吗?
谢谢,
斯蒂芬
I have a ListBox with a nested ListBox inside. Both have ObservableCollections as their ItemsSource set with the inner ListBox's collection being a member of the outer one's Objects...
The collections are filled by a BackgroundWorker which gathers data from a webservice. I had to change from ObservableCollection to an AsyncObservableCollection in order to be able to add items from within the worker's code. AsyncObservableCollection code is from here: Have worker thread update ObservableCollection that is bound to a ListCollectionView
My problem is that the inner ListBox keeps to display duplicate items. It seems as if it always duplicates the first item if it decides to duplicate. I have no clue why this happens. With an event listener attached to the CollectionChanged event of the collection I found out that the event is being fired fine once per item.
Do you have any ideas?
Thanks,
Stephan
发布评论
评论(3)
如果将 ItemsSource 绑定到 AsyncObservableCollection,则必须使用 VistualizingStackPanel 来纠正此问题:
If you bind your ItemsSource to an AsyncObservableCollection, you must using a VistualizingStackPanel to correct this problem :
前几天,我的自定义
INotifyCollectionChanged
集合和TreeView
也遇到了同样的问题。我花了几个小时的调试才找出主要问题是什么。由于我在网络上没有找到任何有关导致这种行为的原因的信息,因此我决定在这里分享我的结果。此行为的根本原因是,显然负责处理由
ItemsControl
控件中的集合引发的CollectionChanged
事件的底层CollectionView
并没有仅依赖NotifyCollectionChangedEventArgs
实例提供的信息来更新 UI。它还考虑了收到通知时收集的内容。考虑对集合执行以下操作:
CollectionChanged
)CollectionChanged
)CollectionChanged
> 第 1 步中执行的清除操作的事件 (NotifyCollectionChangedEventArgs.Action = NotifyCollectionChangedAction.Reset
)CollectionChanged
步骤 2 中执行的添加操作的事件 (NotifyCollectionChangedEventArgs.Action = NotifyCollectionChangedAction.Add
)这样做将使项目 A 在 UI 中出现两次。原因是,当
CollectionView
收到第一个CollectionChanged
通知(第3步)时,它并不关心事件参数的Action
是否是Reset
,它查看集合并发现集合中有一项。因此它将项目添加到控件中。然后,当它收到第二个通知(步骤 4)时,它认为已将新项目添加到集合中,并将该项目再次添加到控件中!我不确定这种行为是否是预期的,但它确实存在。
I had the same issue with my custom
INotifyCollectionChanged
collection and aTreeView
the other day. It took my a few hours of debugging to figure out what the main problem was. As I didn't find any information on what causes this kind of behavior on the web, I decided to share my results here.The root cause of this behavior is that apparently the underlying
CollectionView
that is responsible for handlingCollectionChanged
events raised by the collection inItemsControl
controls, does not solely depend on the information provided by theNotifyCollectionChangedEventArgs
instances to update the UI. It also takes the contents of the collection at the time of receiving the notification into account.Consider performing the following actions to the collection:
CollectionChanged
)CollectionChanged
)CollectionChanged
event for Clear action performed in step 1 (NotifyCollectionChangedEventArgs.Action = NotifyCollectionChangedAction.Reset
)CollectionChanged
event for Add action performed in step 2 (NotifyCollectionChangedEventArgs.Action = NotifyCollectionChangedAction.Add
)Doing so will make item A appear twice in the UI. The reason is that when the
CollectionView
receives the firstCollectionChanged
notification (step 3), it doesn't care if theAction
of the event args isReset
, it looks at the collection and sees there is one item in the collection. So it adds the item to the control. Then when it receives the second notification (step 4), it thinks a new item has been added to the collection and adds the item again to the control!I'm not sure if this behavior is expected or not, but it's there.
我发现 AsyncObservableCollection 导致了问题。显然它搞乱了一些事件或其他什么。
我最终在工作人员的 ProgressChanged 方法中将项目添加到集合中。
I found out that the AsyncObservableCollection caused the problems. Obviously it messed up with some events or whatever.
I ended up in adding items to the collection in the worker's ProgressChanged method.