2009-04-22 5 views
12

Ho due ObservableCollections e ho bisogno di mostrarli insieme in un controllo ListView. A tale scopo ho creato MergedCollection che presenta queste due raccolte come una ObservableCollection. In questo modo posso impostare ListView.ItemsSource nella mia raccolta unita e entrambe le raccolte sono elencate. L'aggiunta funziona bene, ma quando provo a rimuovere un elemento, viene mostrato un'eccezione non gestita:Misto osservabileCollection

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

Il codice di MergedCollection segue:

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 
} 

saluti

risposta

21

v'è alcuna ragione che non può utilizzare CompositeCollection?

Il motivo per cui viene generata l'eccezione è perché non stai traducendo gli indici delle raccolte interne verso l'esterno. Stai semplicemente passando lo stesso evento args all'evento esterno (su MergedCollection), motivo per cui WPF non trova gli elementi in cui l'indice dice di trovarli.

+0

CompositeCollection non implementa INotifyCollectionChanged. –

+1

@Josh: se segui il link, vedrai che lo fa. –

+0

:-). Hai ragione, Kent. È perfetto. Ho seguito il link, ma non ho notato che le interfacce implementate dalla collezione sono su due righe! Ho visto solo IList! –

4

È necessario compensare l'indice dell'evento di notifica.

Dire si rimuove un elemento dalla prima collezione di indice 2. Un evento cambiato collezione è sparato con l'indice 2.

Se si rimuove un elemento dalla seconda raccolta di indice 2, l'evento viene generato con il stesso indice (2), ma l'oggetto viene effettivamente elencato dopo tutti gli elementi nella prima raccolta.

+0

La soluzione di Kent è migliore, ma per la cronaca, ecco cosa era originariamente sbagliato nella tua classe. –

+0

Grazie, ora capisco il problema. I messaggi di eccezione a volte sono un po 'complicati per me. – Zefo