Aktualisieren Sie ItemsControl, wenn ein Objekt in einer ObservableCollection aktualisiert wird

9

Das Problem:

  • Sie deklarieren ein ItemsControl (oder ein von ItemsControl abgeleitetes Steuerelement) in der Ansicht.
  • Sie binden die Eigenschaft ItemsControl.ItemsSource an eine ObservableCollection in Ihrem ViewModel.
  • Ihre Ansicht wird wie erwartet aktualisiert, wenn ein Element zum ObservableCollection hinzugefügt oder daraus entfernt wird.
  • ABER, die Ansicht wird nicht aktualisiert, wenn Sie eine Eigenschaft eines Elements in ObservableCollection ändern.

Hintergrund:

Es scheint, dass dies ein häufiges Problem ist, auf das viele WPF-Entwickler gestoßen sind. Es wurde ein paar Mal gefragt:

ObservableCollection benachrichtigen, wenn sich Artikel ändert

ObservableCollection bemerkt nicht, wenn Item darin steht Änderungen (auch mit INotifyPropertyChanged)

ObservableCollection und Item PropertyChanged

Meine Implementierung:

Ich habe versucht, die akzeptierte Lösung in ObservableCollection benachrichtigen, wenn sich Artikel ändert . Die Grundidee ist, einen PropertyChanged -Handler in Ihrem MainWindowViewModel für jedes Element in ObservableCollection anzuhängen. Wenn die Eigenschaft eines Elements geändert wird, wird der Event-Handler aufgerufen und die View wird irgendwie aktualisiert.

Ich konnte die Implementierung nicht zum Laufen bringen. Hier ist meine Implementierung.

ViewModels:

%Vor%

Artikel ViewModel:

%Vor%

Hauptfenster ViewModel:

%Vor%

Anzeigen:

%Vor%

Meine Ergebnisse:

Um meine Implementierung zu überprüfen, erstelle ich eine Ansicht wie diese. Der TextBlock.Text ist an das erste Element in der Sammlung gebunden. Das ItemsControl ist an die Sammlung selbst gebunden.

  • Wenn Sie auf die Schaltfläche "Add Employee" klicken, wird ein EmployeeViewModel -Objekt in der Sammlung hinzugefügt und sowohl TextBlock als auch ItemsControl werden wie erwartet aktualisiert.
  • Durch erneutes Drücken von "Add Employee" wird ItemsControl mit einem anderen Eintrag aktualisiert. Großartig!
  • Klicken Sie auf die Schaltfläche "Mitarbeiteralter erhöhen". Die Eigenschaft Age jedes Elements wird um 1 erhöht. Das Ereignis PropertyChanged wird ausgelöst. Der ItemPropertyChanged -Ereignishandler wird aufgerufen. Das Textblock wird wie erwartet aktualisiert. Das ItemsControl wird jedoch nicht aktualisiert.

Ich habe den Eindruck, dass das ItemsControl auch aktualisiert werden sollte, wenn das Employee.Age entsprechend der Antwort in ObservableCollection benachrichtigen, wenn sich der Artikel ändert .

    
Frank Liu 10.02.2015, 01:55
quelle

1 Antwort

10

Ich fand die Antwort mit Snoop , um XAML zu debuggen.

Das Problem besteht darin, dass Sie versuchen, an die ToString () -Methode zu binden, wodurch das PropertyChanged-Ereignis nicht ausgelöst wird. Wenn Sie sich die XAML-Bindungen ansehen, werden Sie feststellen, dass sich die ObservableCollection tatsächlich ändert.

Schauen Sie sich nun die einzelnen Elemente an und binden Sie die Texte in die Eigenschaft "Text" ein. Es gibt keine, es ist nur Text.

Um dies zu beheben, fügen Sie einfach eine ItemsControl ItemTemplate mit einer DataTemplate hinzu, die die Elemente enthält, die Sie anzeigen möchten.

%Vor%

Wir haben jetzt grünes Licht für die Bindung. RaisePropertyChanged wird aufgerufen.

Ta-da!

    
AzzamAziz 10.02.2015, 04:36
quelle