Relatives Binding

Beim Konzept des DataBinding werden die Eigenschaften eines Zielobjektes mit den Eigenschaften eines Quellobjektes verbunden, so dass die Änderung einer Quelleigenschaft die Änderung einer Zieleigenschaft bewirkt.

Innerhalb von MVVM (Model View ViewModel) wird dieses Prinzip angewendet um Daten auf einem View-Element anzuzeigen. Hierzu wird in der Regel der BindingContext der View auf eine Instanz des ViewModels gesetzt. Somit kann man die Eigenschaften der View an die Eigenschaften des ViewModels binden.

In den meisten Fällen ist dieser Aufbau ausreichend zur Implementierung der gewünschten Funktionalität. Es gibt jedoch Fälle in denen diese „einfache“ Datenbindung nicht ausreicht:
Wenn man z.B. die ItemSource einer CollectionView an eine ObservableCollection des ViewModels bindet, so entspricht der BindingContext eines (Listen-) Elements genau einem Objekt aus der ObservableCollection.
Wie kann man nun verschiedene Aktionen auf einem Listenelement ausführen (z.B. basierend auf mehreren Buttons) und ggf. noch auf Daten aus dem ViewModel zugreifen?

→ Seit Xamarin 4.3 ist das Relative Binding verfügbar.

Hierdurch ist es möglich die Quelle (source) des gewünschten DataBindings auf eine zu definierende RelativeBindingSource setzen und so dessen Eigenschaften zu binden.

Mit dem Relativen Binding kann man:

• die Eigenschaften eines Elementes an seine eigenen Eigenschaften binden,
• an die Eigenschaften eines direkten Vorfahren (im VisualTree) binden
• die Eigenschaften eines ControlTemplates an die Eigenschaften das anwendenden Controls binden.

→ Für eine ausführliche Beschreibung sei verwiesen auf: Microsoft – Xamarin-Relatives Binding

Angewendet auf obiges Beispiel (Listenelement einer CollectionView) können wir nun im CellTemplate (bzw. Control) mehrere Actions/Events implementieren und diese im ViewModel (dem BindingContext der View) verarbeiten:

(1) Definieren der RelativeBindingSource:

Als Modus wurde hier FindAncestorBindingContext gesetzt und als Typ ILIstCommand. Dadurch wird die Runtime angewiesen, im VisualTree der Seite solange nach einem Vorfahren zu suchen bis einer gefunden wird der dem Typ IListCommand entspricht. (Bei IListCommand handelt es sich um ein eigenes Interface für zu definierende Listenaktionen (Aktion1, Aktion2, Aktion3)).

(2) Verwenden der RelativeBindingSource:

Die CommandProperty unseres Buttons wird an den gewünschten Command gebunden und hierbei der source-Parameter auf die vorher definierte RelativeBindingSource gesetzt. Der „Ziel“ -Command wird hier durch unser Interface (IListCommand) definiert und im ViewModel implementiert.

(3) CommandParameter übergeben

In diesem Fall das zugrunde liegende Listenelement um es im ViewModel auszuwerten.

Im ViewModel wird nun der entsprechende Command des Interface implementiert:

(1) Prüfen des Parameters

Check, ob der angegebene Parameter passt.

(2) Casten der Parameters

Zur besseren Weiterverarbeitung

(3) Ausführen der gewünschten Aktion

Hier z.B. Ausgeben eines Alerts…

 

Ergebnis

Wenn wir nun in obiger Beispiel-Implementierung einen beliebigen Eintrag auswählen und eine Aktion ausführen:

  • Wird zunächst der VisualTree der Ausgabe solange durchsucht bis der zugrunde liegende BindingContext dem Typ IListCommand entspricht
    • Mode=FindAncestorBindingContext,  Typ=IListCommand
  • In dem gefundenen BindingContext wird nun die Implementierung unseres Commands ausgeführt (IListCommand.ElementAction1Command)