Zusammenfassung von Kapitel 18. MVVM
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.
Eine der besten Möglichkeiten zum Entwerfen einer Anwendung besteht darin, die Benutzeroberfläche vom zugrunde liegenden Code zu trennen, der manchmal als Geschäftslogik bezeichnet wird. Es gibt mehrere Methoden, doch die auf XAML-basierte Umgebungen zugeschnittene ist als „Model View ViewModel“ oder „MVVM“ bekannt.
MVVM-Wechselbeziehungen
Eine MVVM-Anwendung weist drei Ebenen auf:
- Das Modell (Model) stellt zugrunde liegende Daten bereit, manchmal durch Dateien oder Webzugriffe.
- Die Ansicht (View) ist die Benutzeroberfläche oder Präsentationsebene, die generell in XAML implementiert wird.
- Das ViewModel verbindet das Modell und die Ansicht.
Das Modell hat keinen Kontakt zum ViewModel, und das ViewModel hat keinen Kontakt zur Ansicht. Diese drei Ebenen stellen generell mithilfe der folgenden Mechanismen eine Verbindung untereinander her:
In vielen kleineren Programmen (und sogar größeren) fehlt häufig das Modell, oder seine Funktionalität ist in das ViewModel integriert.
ViewModels und Datenbindung
Zur Verwendung von Datenbindungen muss ein ViewModel in der Lage sein, die Ansicht zu benachrichtigen, wenn sich eine Eigenschaft des ViewModels geändert hat. Das ViewModel erreicht dies durch Implementierung der INotifyPropertyChanged
-Schnittstelle in den System.ComponentModel
-Namespace. Dies ist nicht Teil von Xamarin.Forms, sondern von .NET. (In der Regel versuchen ViewModels, die Plattformunabhängigkeit aufrechtzuerhalten.)
Die INotifyPropertyChanged
-Schnittstelle deklariert ein einzelnes Ereignis namens PropertyChanged
, das die geänderte Eigenschaft angibt.
Eine ViewModel-Uhr
Das DateTimeViewModel
in der Bibliothek Xamarin.FormsBook.Toolkit definiert eine Eigenschaft vom Typ DateTime
, die sich auf Grundlage eines Timers ändert. Die Klasse implementiert INotifyPropertyChanged
und löst immer das PropertyChanged
-Ereignis aus, wenn sich die DateTime
-Eigenschaft ändert.
Das MvvmClock-Beispiel instanziiert dieses ViewModel und verwendet Datenbindungen an das ViewModel, um aktualisierte Datums- und Uhrzeitinformationen anzuzeigen.
Interaktive Eigenschaften in einem ViewModel
Eigenschaften in einem ViewModel können stärker interaktiv sein, wie von der SimpleMultiplierViewModel
-Klasse veranschaulicht, die Teil des SimpleMultiplier-Beispiels ist. Die Datenbindungen stellen Multiplikand- und Multiplikatorwerte aus zwei Slider
-Elementen bereit und zeigen das Produkt mit einem Label
an. Sie können jedoch umfassende Änderungen an dieser Benutzeroberfläche in XAML vornehmen, ohne dass sich daraus Änderungen am ViewModel oder der CodeBehind-Datei ergeben.
Ein Farb-ViewModel
Das ColorViewModel
in der Bibliothek Xamarin.FormsBook.Toolkit integriert die RGB- und HSL-Farbmodelle. Dies wird im HslSliders-Beispiel veranschaulicht:
Optimieren von ViewModel
Der Code in ViewModels kann optimiert werden, indem eine OnPropertyChanged
-Methode mithilfe des CallerMemberName
-Attributs definiert wird, die den Namen der aufrufenden Eigenschaft automatisch abruft. Die ViewModelBase
-Klasse in der Bibliothek Xamarin.FormsBook.Toolkit leistet dies und stellt eine Basisklasse für ViewModels bereit.
Die Befehlsschnittstelle
MVVM arbeitet mit Datenbindungen, und Datenbindungen arbeiten mit Eigenschaften, sodass MVVM bei der Behandlung eines Clicked
-Ereignisses eines Button
oder eines Tapped
-Ereignisses eines TapGestureRecognizer
unzureichend erscheint. Damit Ereignisse dieser Art mit ViewModels verarbeitet werden können, unterstützt Xamarin.Forms die Befehlsschnittstelle.
Die Befehlsschnittstelle manifestiert sich im Button
mit zwei öffentlichen Eigenschaften:
Command
vom TypICommand
(imSystem.Windows.Input
-Namespace definiert).CommandParameter
vom TypObject
Um die Befehlsschnittstelle zu unterstützen, muss ein ViewModel eine Eigenschaft vom Typ ICommand
definieren, die dann datenmäßig an die Command
-Eigenschaft des Button
gebunden ist. Die ICommand
-Schnittstelle deklariert zwei Methoden und ein Ereignis:
- Eine
Execute
-Methode mit einem Argument vom Typobject
. - Eine
CanExecute
-Methode mit einem Argument vom Typobject
, diebool
zurückgibt. - Ein
CanExecuteChanged
-Ereignis.
Intern legt ein ViewModel jede Eigenschaft vom Typ ICommand
auf eine Instanz einer Klasse fest, die die ICommand
-Schnittstelle implementiert. Durch die Datenbindung ruft der Button
anfänglich die CanExecute
-Methode auf und deaktiviert sich selbst, wenn die Methode false
zurückgibt. Außerdem wird ein Handler für das CanExecuteChanged
-Ereignis festgelegt und immer CanExecute
aufgerufen, wenn dieses Ereignis ausgelöst wird. Wenn Button
aktiviert ist, ruft er immer die Execute
-Methode auf, wenn auf Button
geklickt wird.
Es kann sein, dass Sie über einige ViewModels verfügen, die älter als Xamarin.Forms sind und die Befehlsschnittstelle ggf. bereits unterstützen. Bei neuen ViewModels, die nur für die Verwendung mit Xamarin.Forms gedacht sind, stellt Xamarin.Forms eine Command
-Klasse und eine Command<T>
-Klasse bereit, die die ICommand
-Schnittstelle implementieren. Der generische Typ ist der Typ des Arguments für die Methoden Execute
und CanExecute
.
Einfache Methodenausführungen
Das PowersOfThree-Beispiel veranschaulicht, wie Sie die Befehlsschnittstelle in einem ViewModel verwenden. Die PowersViewModel
-Klasse definiert zwei Eigenschaften vom Typ ICommand
sowie außerdem zwei private Eigenschaften, die an den einfachsten Command
-Konstruktor übergeben werden. Das Programm enthält Datenbindungen von diesem ViewModel an die Command
-Eigenschaften von zwei Button
-Elementen.
Die Button
-Elemente können ohne Codeänderungen ganz einfach in XAML durch TapGestureRecognizer
-Objekte ersetzt werden.
Fast ein Taschenrechner
Im AddingMachine-Beispiel werden die beiden Methoden Execute
und CanExecute
von ICommand
verwendet. Es wird eine AdderViewModel
-Klasse in der Bibliothek Xamarin.FormsBook.Toolkit verwendet. Das ViewModel enthält sechs Eigenschaften vom Typ ICommand
. Diese werden vom Command
-Konstruktor und vom Command
-Konstruktor von Command
sowie vom Command<T>
-Konstruktor von Command<T>
initialisiert. Die numerischen Schlüssel der Rechenmaschine sind alle an die Eigenschaft gebunden, die mit Command<T>
initialisiert wird, und ein string
-Argument an Execute
und CanExecute
identifiziert den jeweiligen Schlüssel.
ViewModels und der Anwendungslebenszyklus
Das im AddingMachine-Beispiel verwendete AdderViewModel
definiert außerdem zwei Methoden namens SaveState
und RestoreState
. Diese Methoden werden von der Anwendung aufgerufen, wenn sie in den Standbymodus wechselt, sowie bei Neustarts.