13

2 つの ObservableCollections があり、それらを 1 つの ListView コントロールで一緒に表示する必要があります。この目的のために、これら 2 つのコレクションを 1 つの ObservableCollection として表示する MergedCollection を作成しました。このようにして、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
}

よろしく

4

2 に答える 2

27

CompositeCollectionを使用できない理由はありますか?

例外がスローされる理由は、内部コレクションのインデックスを外部コレクションに変換していないためです。まったく同じイベント引数を外側のイベント ( on 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>

詳細については、この回答を参照してください。

于 2009-04-22T12:54:10.417 に答える
4

通知イベントのインデックスをオフセットする必要があります。

インデックス 2 の最初のコレクションから項目を削除するとします。コレクション変更イベントはインデックス 2 で発生します。

インデックス 2 の 2 番目のコレクションからアイテムを削除すると、同じインデックス (2) でイベントが発生しますが、アイテムは実際には最初のコレクション内のすべてのアイテムの後に列挙されます。

于 2009-04-22T13:14:13.770 に答える