views:

1335

answers:

2

Hello,

I have two ObservableCollections and I need to show them in one ListView control together. For this purpose I created MergedCollection which presents these two collections as one ObservableCollection. This way I can set the ListView.ItemsSource to my merged collection and both collections are listed. Adding works fine but when I try to Remove an item, unhandled exception is shown:

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

The code of MergedCollection follows:

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
}

Regards

+6  A: 

Is there any reason you can't use CompositeCollection?

The reason the exception is being thrown is because you're not translating the indexes of the inner collections to the outer. You're just passing the exact same event args to the outer event (on MergedCollection), which is why WPF doesn't find the items where the index is telling it to find them.

HTH, Kent

Kent Boogaart
CompositeCollection doesn't implement INotifyCollectionChanged.
Josh G
@Josh: If you follow the link, you'll see that it does.
Kent Boogaart
:-). You are right, Kent. That's perfect. I followed the link, but I didn't notice that the interfaces that the collection implements are on two lines! I only saw IList!
Josh G
Hi Kent, thank you very much, the CompositeCollection is perfect. I am still learning .NET and WPF and I somehow overlooked it. Thanks.
Zefo
No problem guys.
Kent Boogaart
Awesome, I've been looking for something like this for quite some time. Thanks, Kent! (My only complaint is that it's not strongly typed.)
mattdekrey
+1  A: 

You have to offset the index of the notification event.

Say you remove an item from the first collection at index 2. A collection changed event is fired with index 2.

If you remove an item from the second collection at index 2, the event is fired with the same index (2), but the item is actually enumerated after all of the items in the first collection.

Josh G
Kent's solution is better, but for the record, here's what was originally wrong with your class.
Josh G
Thank you, now I understand the problem. The exception messages are sometimes a bit tricky for me.
Zefo