WPF 列表框显示重复的项目。如何出行?

发布于 2024-11-27 04:13:59 字数 645 浏览 3 评论 0 原文

我有一个列表框,里面有一个嵌套的列表框。两者都将 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

此刻的回忆 2024-12-04 04:13:59

如果将 ItemsSource 绑定到 AsyncObservableCollection,则必须使用 VistualizingStackPanel 来纠正此问题:

<ListBox
 ItemTemplate="{StaticResource YourItemTemplate}"
 ItemsSource="{Binding Path=YourAsyncObservableCollection}" 
 ScrollViewer.CanContentScroll="False"
 ScrollViewer.HorizontalScrollBarVisibility="Auto"
 ScrollViewer.VerticalScrollBarVisibility="Disabled"
 Style="{DynamicResource YourListBoxStyle}">
 <ListBox.ItemsPanel>
  <ItemsPanelTemplate>
   <VirtualizingStackPanel Orientation="Vertical" />
  </ItemsPanelTemplate>
 </ListBox.ItemsPanel>
</ListBox>

If you bind your ItemsSource to an AsyncObservableCollection, you must using a VistualizingStackPanel to correct this problem :

<ListBox
 ItemTemplate="{StaticResource YourItemTemplate}"
 ItemsSource="{Binding Path=YourAsyncObservableCollection}" 
 ScrollViewer.CanContentScroll="False"
 ScrollViewer.HorizontalScrollBarVisibility="Auto"
 ScrollViewer.VerticalScrollBarVisibility="Disabled"
 Style="{DynamicResource YourListBoxStyle}">
 <ListBox.ItemsPanel>
  <ItemsPanelTemplate>
   <VirtualizingStackPanel Orientation="Vertical" />
  </ItemsPanelTemplate>
 </ListBox.ItemsPanel>
</ListBox>
活雷疯 2024-12-04 04:13:59

前几天,我的自定义 INotifyCollectionChanged 集合和 TreeView 也遇到了同样的问题。我花了几个小时的调试才找出主要问题是什么。由于我在网络上没有找到任何有关导致这种行为的原因的信息,因此我决定在这里分享我的结果。

此行为的根本原因是,显然负责处理由 ItemsControl 控件中的集合引发的 CollectionChanged 事件的底层 CollectionView 并没有仅依赖 NotifyCollectionChangedEventArgs 实例提供的信息来更新 UI。它还考虑了收到通知时收集的内容。

考虑对集合执行以下操作:

  1. 清除集合(不引发 CollectionChanged
  2. 将项目 A 添加到集合中(不引发 CollectionChanged
  3. 引发 CollectionChanged > 第 1 步中执行的清除操作的事件 (NotifyCollectionChangedEventArgs.Action = NotifyCollectionChangedAction.Reset)
  4. 引发 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 a TreeView 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 handling CollectionChanged events raised by the collection in ItemsControl controls, does not solely depend on the information provided by the NotifyCollectionChangedEventArgs 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:

  1. Clear the collection (without raising CollectionChanged)
  2. Add item A to the collection (without raising CollectionChanged)
  3. Raise CollectionChanged event for Clear action performed in step 1 (NotifyCollectionChangedEventArgs.Action = NotifyCollectionChangedAction.Reset)
  4. Raise 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 first CollectionChanged notification (step 3), it doesn't care if the Action of the event args is Reset, 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.

勿忘心安 2024-12-04 04:13:59

我发现 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文