Freigeben über


Zusammenfassung von Kapitel 16. Datenbindung

Hinweis

Dieses Buch wurde im Frühjahr 2016 veröffentlicht und seitdem nicht aktualisiert. Wenngleich ein großer Teil des Buchs weiterhin relevante Informationen liefert, sind einige Abschnitte veraltet, und einige Themen sind nicht mehr korrekt oder vollständig.

Programmierer müssen oft Ereignishandler schreiben, die erkennen, wenn sich eine Eigenschaft eines Objekts geändert hat, und dies nutzen, um den Wert einer Eigenschaft in einem anderen Objekt zu ändern. Dieser Prozess kann mithilfe einer Datenbindung genannten Technik automatisiert werden. Datenbindungen werden in der Regel in XAML definiert und Teil der Definition der Benutzeroberfläche.

Sehr oft verbinden diese Datenbindungen Benutzeroberflächenobjekte mit zugrunde liegenden Daten. Dies ist eine Technik, die in Kapitel 18 genauer untersucht wird. MVVM. Datenbindungen können jedoch auch zwei oder mehr Benutzeroberflächenelemente verbinden. In den meisten der frühen Beispiele für Datenbindung in diesem Kapitel wird diese Technik veranschaulicht.

Grundlagen der Datenbindung

An der Datenbindung sind mehrere Eigenschaften, Methoden und Klassen beteiligt:

Die beiden folgenden Klassen unterstützen XAML-Markuperweiterungen für Bindungen:

An der Datenbindung sind zwei Schnittstellen beteiligt:

  • INotifyPropertyChanged im Namespace System.ComponentModel dient der Implementierung der Benachrichtigung bei Änderung einer Eigenschaft.
  • IValueConverter dient zur Definition kleiner Klassen, die in Datenbindungen Werte von einem Typ in einen anderen konvertieren.

Eine Datenbindung verbindet zwei Eigenschaften desselben Objekts oder (häufiger) zwei verschiedene Objekte. Diese beiden Eigenschaften werden als Quelle und Ziel bezeichnet. Im Allgemeinen bewirkt eine Änderung der Quelleigenschaft eine Änderung der Zieleigenschaft, doch mitunter wird die Richtung umgekehrt. Stets gilt jedoch:

Eine Klasse, die INotifyPropertyChanged implementiert, löst das Ereignis PropertyChanged aus, sobald eine Eigenschaft ihren Wert ändert. BindableObject implementiert INotifyPropertyChanged und löst automatisch das Ereignis PropertyChanged aus, wenn eine durch BindableProperty unterstützte Eigenschaft Werte ändert. Sie können jedoch eigene Klassen schreiben, die INotifyPropertyChanged ohne Ableitung von BindableObject implementieren.

Code und XAML

Das Beispiel OpacityBindingCode zeigt, wie eine Datenbindung im Code festgelegt werden kann:

  • Die Quelle ist die Value-Eigenschaft eines Slider-Objekts.
  • Das Ziel ist die Opacity-Eigenschaft eines Label-Objekts.

Die beiden Objekte werden durch Festlegen von BindingContext des Label-Objekts mit dem Slider-Objekt verbunden. Die beiden Eigenschaften werden durch den Aufruf der Erweiterungsmethode SetBinding für das Label-Objekt verbunden. Dabei wird auf die bindbare Eigenschaft OpacityProperty und die Value-Eigenschaft des Slider-Objekts, ausgedrückt als Zeichenfolge, verwiesen.

Wenn Sie das Slider-Objekt bearbeiten, wird das Label-Objekt aus der Ansicht ausgeblendet.

OpacityBindingXaml ist dasselbe Programm, bei dem die Datenbindung in XAML festgelegt ist. BindingContext des Label-Objekts wird auf die Markuperweiterung x:Reference festgelegt, die auf Slider verweist. Die Eigenschaft Opacity des Label-Objekts wird auf die Markuperweiterung Binding festgelegt, wobei die Eigenschaft Path auf die Value-Eigenschaft von Slider verweist.

Quelle und BindingContext

Das Beispiel BindingSourceCode zeigt einen alternativen Ansatz im Code. Ein Binding-Objekt wird erstellt, indem die Source-Eigenschaft auf das Slider-Objekt und die Path-Eigenschaft auf „Wert“ festgelegt wird. Die SetBinding-Methode von BindableObject wird dann für das Label-Objekt aufgerufen.

Der Binding-Konstruktor kann auch zum Definieren des Binding-Objekts verwendet werden.

Das Beispiel BindingSourceXaml zeigt die vergleichbare Technik in XAML. Die Opacity-Eigenschaft von Label wird auf die Markuperweiterung Binding festgelegt, wobei Path auf die Value-Eigenschaft und Source auf die eingebettete Markuperweiterung x:Reference festgelegt wird.

Zusammenfassend gibt es zwei Möglichkeiten, auf das Bindungsquellobjekt zu verweisen:

  • Über die BindingContext-Eigenschaft des Ziels
  • Über die Source-Eigenschaft des Binding-Objekts selbst

Wenn beides angegeben wird, hat die zweite Vorrang. Der Vorteil von BindingContext besteht darin, dass die Weitergabe durch die visuelle Struktur erfolgt. Dies ist sehr praktisch, wenn mehrere Zieleigenschaften an dasselbe Quellobjekt gebunden sind.

Das Programm WebViewDemo demonstriert diese Technik mit dem Element WebView. Zwei Button-Elemente zur Vor- und Rückwärtsnavigation erben BindingContext von ihrem übergeordneten Element, das auf WebView verweist. Die IsEnabled-Eigenschaften der beiden Schaltflächen haben dann einfache Markuperweiterungen des Typs Binding, die auf die IsEnabled-Eigenschaften der Schaltfläche abzielen, und zwar auf der Grundlage der Einstellungen für CanGoBack und der schreibgeschützten CanGoForward-Eigenschaften der WebView.

Der Bindungsmodus

Legen Sie die Mode-Eigenschaft von Binding auf einen Member der BindingMode-Enumeration fest:

  • OneWay, damit sich Änderungen in der Quelleigenschaft auf das Ziel auswirken.
  • OneWayToSource, damit sich Änderungen in der Zieleigenschaft auf die Quelle auswirken.
  • TwoWay, damit sich Änderungen in Quelle und Ziel gegenseitig beeinflussen.
  • Default, damit der DefaultBindingMode verwendet wird, der beim Erstellen der Ziel-BindableProperty angegeben wurde. Wenn nichts angegeben wurde, ist der Standard OneWay für normale bindbare Eigenschaften und OneWayToSource für schreibgeschützte bindbare Eigenschaften.

Hinweis

Die Enumeration BindingMode enthält nun auch OnTime, um eine Bindung nur dann anzuwenden, wenn sich der Bindungskontext ändert, und nicht, wenn sich die Quelleigenschaft ändert.

Eigenschaften, die voraussichtlich das Ziel von Datenbindungen in MVVM-Szenarien sein werden, haben im Allgemeinen die DefaultBindingMode-Einstellung TwoWay. Dies sind:

  • die Value-Eigenschaft von Slider und Stepper
  • die IsToggled-Eigenschaft von Switch
  • die Text-Eigenschaft von Entry, Editor und SearchBar
  • die Date-Eigenschaft von DatePicker
  • die Time-Eigenschaft von TimePicker

Das Beispiel BindingModes veranschaulicht die vier Bindungsmodi mit einer Datenbindung, bei der das Ziel die FontSize-Eigenschaft eines Label-Elements und die Quelle die Value-Eigenschaft eines Slider-Elements ist. Dies ermöglicht es jedem Slider-Element, den Schriftgrad des entsprechenden Label-Elements zu steuern. Die Slider-Elemente werden jedoch nicht initialisiert, weil der DefaultBindingMode der FontSize-Eigenschaft OneWay ist.

Das Beispiel ReverseBinding legt die Bindungen für die Value-Eigenschaft des Slider-Elements fest, die auf die FontSize-Eigenschaft jedes Label-Elements verweist. Das scheint verkehrt herum zu sein, aber es funktioniert besser bei der Initialisierung der Slider-Elemente, weil die Value-Eigenschaft des Slider-Elements die DefaultBindingMode-Einstellung TwoWay hat.

Dreifacher Screenshot der umgekehrten Bindung

Dies ist analog zur Definition von Bindungen in MVVM. Sie werden diese Art von Bindung häufig verwenden.

Zeichenfolgenformatierung

Wenn die Zieleigenschaft den Typ string hat, können Sie die von BindingBase definierte StringFormat-Eigenschaft verwenden, um die Quelle in string zu konvertieren. Legen Sie die StringFormat-Eigenschaft auf eine .NET-Formatierungszeichenfolge fest, die Sie mit dem statischen Format String.Format zum Anzeigen des Objekts verwenden. Bei Verwenden dieser Formatierungszeichenfolge innerhalb einer Markuperweiterung umgeben Sie diese mit einfachen Anführungszeichen, damit die geschweiften Klammern nicht mit einer eingebetteten Markuperweiterung verwechselt werden.

Das Beispiel ShowViewValues veranschaulicht die Verwendung von StringFormat in XAML.

Das Beispiel WhatSizeBindings demonstriert die Darstellung der Größe der Seite mit Bindungen an die Eigenschaften Width und Height von ContentPage.

Warum lautet der Name „Path“?

Die Eigenschaft Path von Binding wird so genannt, weil es sich um eine Reihe von Eigenschaften und Indexern handeln kann, die durch Punkte getrennt sind. Das Beispiel BindingPathDemos zeigt mehrere Beispiele.

Bindungswertkonverter

Wenn die Quell- und Zieleigenschaften einer Bindung unterschiedliche Typen sind, können Sie mit einem Bindungskonverter die Konvertierung zwischen den Typen vornehmen. Dies ist eine Klasse, die die Schnittstelle IValueConverter implementiert und zwei Methoden enthält: Convert zur Konvertierung der Quelle in das Ziel und ConvertBack zur Konvertierung des Ziels in die Quelle.

Die IntToBoolConverter-Klasse in der Bibliothek Xamarin.FormsBook.Toolkit ist ein Beispiel für das Konvertieren von int in bool. Dies wird durch das Beispiel ButtonEnabler veranschaulicht, das Button nur dann aktiviert, wenn mindestens ein Zeichen in Entry eingegeben wurde.

Die Klasse BoolToStringConverter konvertiert bool in string und definiert zwei Eigenschaften, um anzugeben, welcher Text für die Werte false und true zurückgegeben werden soll. BoolToColorConverter ist ähnlich. Das Beispiel SwitchText demonstriert die Verwendung dieser beiden Konverter zur Anzeige unterschiedlicher Texte in unterschiedlichen Farben auf Grundlage einer Switch-Einstellung.

Der generische BoolToObjectConverter kann BoolToStringConverter und BoolToColorConverter ersetzen und als universeller bool-zu-Objekt-Konverter beliebiger Typen dienen.

Bindungen und benutzerdefinierte Ansichten

Mithilfe von Datenbindungen können Sie benutzerdefinierte Steuerelemente vereinfachen. Die Codedatei NewCheckBox.cs definiert die Eigenschaften Text, TextColor, FontSize, FontAttributes und IsChecked, enthält jedoch keinerlei Logik für die visuelle Darstellung des Steuerelements. Stattdessen enthält die Datei NewCheckBox.cs.xaml das gesamte Markup für die visuellen Elemente des Steuerelements durch Datenbindungen an die Label-Elemente, und zwar auf Grundlage der in der CodeBehind-Datei definierten Eigenschaften.

Das Beispiel NewCheckBoxDemo veranschaulicht das benutzerdefinierte Steuerelement NewCheckBox.