3

Ich habe den folgenden Testcode:WPF ListBox Bindung nicht zu INotifyCollectionChanged oder INotifyPropertyChanged Events

private class SomeItem 
    { 
     public string Title{ get{ return "something"; } } 
     public bool Completed { get { return false; } set { } } 
    } 

    private class SomeCollection : IEnumerable<SomeItem>, INotifyCollectionChanged 
    { 
     private IList<SomeItem> _items = new List<SomeItem>(); 
     public void Add(SomeItem item) 
     { 
      _items.Add(item); 
      CollectionChanged(this, new 
      NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 
     } 

     #region IEnumerable<SomeItem> Members 

     public IEnumerator<SomeItem> GetEnumerator() 
     { 
      return _items.GetEnumerator(); 
     } 

     #endregion 

     #region IEnumerable Members 

     System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
     { 
      return _items.GetEnumerator(); 
     } 

     #endregion 

     #region INotifyCollectionChanged Members 

     public event NotifyCollectionChangedEventHandler CollectionChanged; 

     #endregion 
    } 

    private SomeCollection collection = new SomeCollection(); 

    private void Expander_Expanded(object sender, RoutedEventArgs e) 
    { 
     var expander = (Expander) sender; 
     var list = expander.DataContext as ITaskList; 
     var listBox = (ListBox)expander.Content; 
     //list.Tasks.CollectionChanged += CollectionChanged; 
     collection.Add(new SomeItem()); 
     collection.Add(new SomeItem()); 
     listBox.ItemsSource = collection; 
    } 

und die XAML

<ListBox Name="taskListList" ItemsSource="{Binding}" BorderThickness="0" ItemContainerStyle="{StaticResource noSelectedStyle}" > 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
      <Expander Expanded="Expander_Expanded"> 
       <Expander.Header> 
       <StackPanel Orientation="Horizontal"> 
        <TextBlock Text="{Binding Name}" /> 
        <TextBox KeyUp="TextBox_KeyUp" Width="200"/> 
        <Button Name="hide" Click="hide_Click"> 
         <TextBlock Text="hide" /> 
        </Button> 
       </StackPanel> 
       </Expander.Header> 
        <ListBox Name="taskList" ItemsSource="{Binding}" ItemTemplate=" 
        {StaticResource taskItem}" /> 
       </Expander> 
     </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 

die äußere listbox auf Last bevölkert wird. wenn der Expander expandiert wird ich dann den ItemsSource Eigenschaft des inneren listbox (der Grund, warum ich diese stattdessen Bindung hören Sie zu verwenden, ist dieser Vorgang ziemlich langsam ist, und ich will es nur stattfinden, wenn die Verwendung der Elemente anzuzeigen, wählt). Das innere Listenfeld wird ordnungsgemäß gerendert, es wird jedoch nicht tatsächlich für das Ereignis CollectionChanged der Sammlung abonniert. Ich habe schon versucht, diese mit ICollection statt IEnumerable und das Hinzufügen von INotifyPropertyChanged sowie Ersatz INotifyCollectionChanged mit INotifyPropertyChanged. Der einzige Weg, wie ich das zum Laufen bringen kann, ist meine SomeCollection Klasse zu erben und von ObservableCollection<SomeItem> zu erben. Meine Argumentation für den Versuch, meine eigene INotifyCollectionChanged anstelle von ObservableCollection zu verwenden, ist, weil ich eine COM-Sammlung in den echten Code verpacken. Diese Sammlung benachrichtigt bei Hinzufügen/Ändern/Entfernen und ich versuche, diese in INotify Ereignisse für WPF zu konvertieren.

Hoffnung ist klar genug (sein spät).

+1

Ich vermute, es ist, weil Sie 'INotifyCollectionChanged' Verhalten nicht ausreichend implementieren, und Sie implementieren nicht' INotifyPropertyChanged' überhaupt. Es lohnt sich wahrscheinlich nicht, die spezifischen Gründe zu ermitteln, da Sie besser 'SomeCollection' von ObservableCollection erben und viel für Sie erledigen müssen. Warum erfinden Sie das Rad neu? Sie können weiterhin Methoden überschreiben, um das Verhalten bei Bedarf anzupassen. –

+0

Haben Sie weitere Details zu der COM-Sammlung, die Sie umbrechen möchten? Ich denke, Sie sollten sich fragen, wie Sie Ihre COM-Sammlung in eine ObservableCollection konvertieren. – Iain

Antwort

0

ObservableCollection<T> implementiert auch INotifyPropertyChanged. Wie Sie Sammlung einfach ein IEnumerable<T> Sie haben keine Eigenschaften Ereignisse zu schaffen, aber ObservableCollection<T>PropertyChanged Veranstaltungen für die Count und Item[] Eigenschaften erstellen. Sie könnten versuchen, Ihre Sammlung eher wie ObservableCollection<T> zu gestalten, indem Sie von IList<T> ableiten und INotifyPropertyChanged implementieren. Ich weiß nicht, ob das dein Problem beheben wird.

+0

Wenn ich die Frage richtig verstehe, existiert die Sammlung bereits und hat eine Basisklasse, die nicht ObservableCollection ist. Obwohl diese Sammlung INotifyCollectionChanged implementiert, erzwingt diese Auflistung keine Aktualisierung der Listbox, wenn sie geändert wird. Die Frage ist warum? –

0

Ich verstehe nicht, warum ich Menschen sehe immer wieder versuchen, ihre eigenen Sammlungen in WPF zu implementieren. Verwenden Sie einfach eine ObservableCollection<SomeItem> und alle Ihre CollectionChanged Benachrichtigungen werden erledigt.

private ObservableCollection<SomeItem> collection = 
    new ObservableCollection<SomeItem>(); 

Wenn Sie etwas auf SomeItem.PropertyChanged passieren sollen, SomeItemINotifyPropertyChanged

Was, warum Ihre Collection angehoben wird nicht umsetzen lassen, sind Sie die Itemssource-Eigenschaft, nicht Bindung es. Wenn Sie es einstellen, bedeutet das, dass Sie eine Kopie von collection erstellen und in ListBox.ItemsSource speichern. Binden bedeutet, dass Sie ListBox.ItemsSource mitteilen würden, um auf collection für seine Daten zu verweisen.

+0

Nun, ObservableCollection implementiert keine Sortierung. Wenn Sie also Ihre Daten sortiert haben möchten, müssen Sie eine andere Sammlung erweitern und INotifyCollectionChanged implementieren. – Adarsha

+1

@Adarsha Ich erweitere nur 'ObservableCollection ', um eine 'Sort' Methode einzuschließen. Ich erstelle keine Klasse, die von ObservableCollection für dieses Verhalten erbt. Sie können ein Beispiel der Sortiercode in [dieser Antwort] (http://stackoverflow.com/a/7285548/302677) – Rachel

+0

beachten, dass OP ObservableCollection nicht erweitert hat, stattdessen versuchte er INotifyCollectionChanged zu implementieren. Was erwartet Sie, OnCollectionChanged zu implementieren. Beachten Sie, dass ObservableCollection.Move nicht in allen .NET-Versionen verfügbar ist, z. Windows Phone. Um Sort zu implementieren, müssen wir damit beginnen, das Rad zum Sortieren neu zu erfinden. Es verwendet entweder eine Klasse, die IList implementiert , INotifyCollectionChanged, oder ObservableCollection und reinvet Sorting from the scratch. – Adarsha