合并的 ObservableCollection

Posted

技术标签:

【中文标题】合并的 ObservableCollection【英文标题】:Merged ObservableCollection 【发布时间】:2010-10-21 02:15:53 【问题描述】:

我有两个 ObservableCollections,我需要将它们一起显示在一个 ListView 控件中。为此,我创建了 MergedCollection,它将这两个集合呈现为一个 ObservableCollection。这样,我可以将 ListView.ItemsSource 设置为我的合并集合,并列出两个集合。添加工作正常,但当我尝试删除项目时,显示未处理的异常:

An unhandled exception of type 'System.InvalidOperationException' occurred in PresentationFramework.dll
Additional information: Added item does not appear at given index '2'.

MergedCollection 的代码如下:

public class MergedCollection : IEnumerable, INotifyCollectionChanged

    ObservableCollection<NetworkNode> nodes;
    ObservableCollection<NodeConnection> connections;

    public MergedCollection(ObservableCollection<NetworkNode> nodes, ObservableCollection<NodeConnection> connections)
    
        this.nodes = nodes;
        this.connections = connections;

        this.nodes.CollectionChanged += new NotifyCollectionChangedEventHandler(NetworkNodes_CollectionChanged);
        this.connections.CollectionChanged += new NotifyCollectionChangedEventHandler(Connections_CollectionChanged);
    

    void NetworkNodes_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    
        CollectionChanged(this, e);
    

    void Connections_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    
        CollectionChanged(this, e);
    

    #region IEnumerable Members

    public IEnumerator GetEnumerator()
    
        for (int i = 0; i < connections.Count; i++)
        
            yield return connections[i];
        

        for (int i = 0; i < nodes.Count; i++)
        
            yield return nodes[i];
        
    

    #endregion

    #region INotifyCollectionChanged Members

    public event NotifyCollectionChangedEventHandler CollectionChanged;

    #endregion

问候

【问题讨论】:

【参考方案1】:

你有什么理由不能使用CompositeCollection?

抛出异常的原因是您没有将内部集合的索引转换为外部集合。您只是将完全相同的事件参数传递给外部事件(在 MergedCollection 上),这就是 WPF 找不到索引告诉它找到它们的项目的原因。

你像这样使用CompositeCollection

<ListBox>
  <ListBox.Resources>
    <CollectionViewSource x:Key="DogCollection" Source="Binding Dogs"/>
    <CollectionViewSource x:Key="CatCollection" Source="Binding Cats"/>
  </ListBox.Resources>
  <ListBox.ItemsSource>
    <CompositeCollection>
      <CollectionContainer Collection="Binding Source=StaticResource DogCollection"/>
      <CollectionContainer Collection="Binding Source=StaticResource CatCollection"/>
    </CompositeCollection>
   </ListBox.ItemsSource>
   <!-- ... -->
</ListBox>

详情请见this answer。

【讨论】:

CompositeCollection 没有实现 INotifyCollectionChanged。 @Josh:如果你点击链接,你会看到它确实如此。 :-)。你是对的,肯特。那很完美。我跟着链接,但我没有注意到集合实现的接口在两行!我只看到了 IList! 您好 Kent,非常感谢您,CompositeCollection 非常完美。我仍在学习 .NET 和 WPF,但不知何故忽略了它。谢谢。 太棒了,我一直在寻找类似的东西已经有一段时间了。谢谢,肯特! (我唯一的抱怨是它不是强类型的。)【参考方案2】:

你必须偏移通知事件的索引。

假设您从索引 2 处的第一个集合中删除了一个项目。集合更改事件会在索引 2 处触发。

如果您从索引 2 处的第二个集合中删除一个项目,则使用相同的索引 (2) 触发该事件,但该项目实际上是在第一个集合中的所有项目之后枚举的。

【讨论】:

Kent 的解决方案更好,但为了记录,这就是你的班级最初的问题。 谢谢,现在我明白了这个问题。异常消息有时对我来说有点棘手。

以上是关于合并的 ObservableCollection的主要内容,如果未能解决你的问题,请参考以下文章

excel表格合并后居中的方法步骤

HTMLHTML 表格 ③ ( 合并单元格 | 跨行合并 | 跨列合并 | 单元格合并顺序 | 跨行设置 rowspan 属性 | 跨列设置 colspan 属性 )

多个EXCEL的CSV文件合并时会把每个文件的表头重复合并到结果文件里,能否让合并结果只有一个表头呢?

合并排序——二路合并排序

dp之沙子合并 环形沙子合并 沙子合并加强 沙子三兄弟的故事

石子合并问题 C语言