WPF ListBox 显示重复项。如何四处走动?

Posted

技术标签:

【中文标题】WPF ListBox 显示重复项。如何四处走动?【英文标题】:WPF ListBox displays duplicate items. How to get around? 【发布时间】:2011-10-17 05:53:25 【问题描述】:

我有一个 ListBox,里面有一个嵌套的 ListBox。两者都将 ObservableCollections 作为其 ItemsSource 集,内部 ListBox 的集合是外部对象的成员...

集合由一个从网络服务收集数据的 BackgroundWorker 填充。我必须从 ObservableCollection 更改为 AsyncObservableCollection 才能从工作人员的代码中添加项目。 AsyncObservableCollection 代码来自这里:Have worker thread update ObservableCollection that is bound to a ListCollectionView

我的问题是内部 ListBox 不断显示重复项。如果它决定复制,它似乎总是复制第一个项目。我不知道为什么会这样。通过附加到集合的 CollectionChanged 事件的事件侦听器,我发现每个项目都会触发一次该事件。

你有什么想法吗?

谢谢, 斯蒂芬

【问题讨论】:

你将不得不在这里给我们一些更多的细节。尝试将您的代码缩减为仍然存在此问题的最小示例,然后更新您的问题以包含所有代码。 不幸的是,我无法在一个小示例中重现该行为。除此之外,我不允许将我的代码发布到网上,所以我想我必须自己处理这个问题。感谢所有愿意提供帮助的人;) 【参考方案1】:

如果您将 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>

【讨论】:

【参考方案2】:

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

这种行为的根本原因显然是底层的CollectionView 负责处理ItemsControl 控件中的集合引发的CollectionChanged 事件,不仅仅依赖于NotifyCollectionChangedEventArgs 实例提供的信息更新用户界面。它还考虑了收到通知时集合的内容。

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

    清除集合(不引发CollectionChanged) 将项目 A 添加到集合中(不引发 CollectionChanged) 引发CollectionChanged 事件以清除在步骤 1 中执行的操作 (NotifyCollectionChangedEventArgs.Action = NotifyCollectionChangedAction.Reset) 为步骤 2 中执行的添加操作引发 CollectionChanged 事件 (NotifyCollectionChangedEventArgs.Action = NotifyCollectionChangedAction.Add)

这样做会使项目 A 在 UI 中出现两次。原因是当CollectionView 收到第一个CollectionChanged 通知时(步骤3),它不关心事件args 的Action 是否为Reset,它查看集合并看到有一个集合中的项目。所以它将项目添加到控件中。然后当它收到第二个通知(第 4 步)时,它认为一个新项目已添加到集合中并再次将该项目添加到控件中!

我不确定这种行为是否在意料之中,但确实存在。

【讨论】:

【参考方案3】:

我发现 AsyncObservableCollection 导致了这些问题。显然它搞砸了一些事件或其他什么。 我最终在工作人员的 ProgressChanged 方法中将项目添加到集合中。

【讨论】:

你能再解释一下吗?我有同样的问题。顺便说一句,这似乎是一个时间问题(如果我在向 AsyncObservableCollection 添加内容时等待 100 毫秒,则没有幽灵项目。奇怪 - 无论如何,我没有得到你的解决方案,你能解释一下吗?你放弃了 AsyncObservableCollection 吗?

以上是关于WPF ListBox 显示重复项。如何四处走动?的主要内容,如果未能解决你的问题,请参考以下文章

wpf中如何绑定到listbox中的选定项

WPF中ListBox连续选择同一项时SelectionChanged 事件不响应的问题

wpf画面ListBox绑定的数据发生变化时 画面闪烁

如何在WPF中使用ListBox对键和值进行分组

WPF:将 ListBox ContextMenu 的命令参数绑定到 ListBox 的选定项

加载 WPF 时在 ListBox 中设置选定项的样式