Объединенная коллекция ObservableCollection - PullRequest
12 голосов
/ 22 апреля 2009

У меня есть две 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
}

Привет

Ответы [ 2 ]

22 голосов
/ 22 апреля 2009

Есть ли причина, по которой вы не можете использовать 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>

Подробнее см. в этом ответе .

4 голосов
/ 22 апреля 2009

Вы должны сместить индекс события уведомления.

Скажем, вы удаляете элемент из первой коллекции по индексу 2. Событие изменения коллекции запускается с индексом 2.

Если вы удаляете элемент из второй коллекции по индексу 2, событие вызывается с тем же индексом (2), но элемент фактически перечисляется после всех элементов в первой коллекции.

...