WPF ListBox显示重复的项目。怎么到处走?

时间:2011-08-01 07:30:02

标签: wpf asynchronous listbox backgroundworker observablecollection

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

这些集合由BackgroundWorker填充,后者从Web服务收集数据。我不得不从ObservableCollection更改为AsyncObservableCollection,以便能够从worker的代码中添加项目。 AsyncObservableCollection代码来自此处:Have worker thread update ObservableCollection that is bound to a ListCollectionView

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

你有什么想法吗?

谢谢, 斯蒂芬

3 个答案:

答案 0 :(得分: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>

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

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

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

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

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

我不确定这种行为是否符合预期,但确实存在。