【问题标题】:WPF ListBox displays duplicate items. How to get around?WPF ListBox 显示重复项。如何四处走动?
【发布时间】: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 事件的事件侦听器,我发现每个项目都会触发一次该事件。

你有什么想法吗?

谢谢, 斯蒂芬

【问题讨论】:

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

标签: wpf asynchronous listbox backgroundworker observablecollection


【解决方案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 实例提供的信息更新用户界面。它还考虑了收到通知时集合的内容。

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

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

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 你能再解释一下吗?我有同样的问题。顺便说一句,这似乎是一个时间问题(如果我在向 AsyncObservableCollection 添加内容时等待 100 毫秒,则没有幽灵项目。奇怪 - 无论如何,我没有得到你的解决方案,你能解释一下吗?你放弃了 AsyncObservableCollection 吗?
      猜你喜欢
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-22
      • 2010-12-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多