Verwenden von Befehlen in einer ViewModel-Komponente
Sie haben gesehen, wie Sie Daten von Ihren Viewmodels auf Ihre Benutzeroberfläche abrufen und wie Sie bidirektionale Bindung verwenden können, um Daten wieder in Ihre Ansichtsmodelle zu integrieren.
Die Verwendung bidirektionaler Bindungen ist die bevorzugte Methode, auf Änderungen der Benutzeroberfläche zu reagieren, bei denen Daten geändert werden. Viele Dinge, die als Ereignisse behandelt werden, können unter Verwendung bidirektionaler Bindungen und MVVM verarbeitet werden. Andere Beispiele sind Dinge wie Switch.IsToggled
und Slider.Value
, die in unserem ViewModel als booleschen oder ganzzahligen Wert widergespiegelt werden können, ohne Ereignisse verwenden zu müssen.
Aber es gibt auch Vorgänge wie z.B. eine Button
- oder MenuItem
-Aktivierung, die nicht direkt an eine Datenänderung gebunden sind. Diese Interaktionen erfordern dennoch ereignisähnliche Verarbeitung. Da diese UI-Komponenten in der Regel eine Art Von Logik mit den Daten aufrufen, möchten wir diese Logik für das ViewModel. Aber wir möchten sie nicht als Clicked
und Selected
-Ereignisse im CodeBehind behandeln, wenn möglich. Wir möchten so viel wie möglich im ViewModel sein, auf diese Weise ist es testbar.
Verwenden des Command-Musters
Viele der .NET MAUI-Steuerelemente, die über diese Art von Interaktionsunterstützung verfügen, unterstützen die Bindung an eine Eigenschaft, die eine ICommand
Schnittstelle verfügbar macht. Diese Eigenschaft hat höchstwahrscheinlich den Namen Command
. Die Schaltfläche ist ein Beispiel:
<Button Text="Give Bonus" Command="{Binding GiveBonus}" />
Das Steuerelement weiß, wann der Befehl aufgerufen werden soll. Beispielsweise ruft eine Schaltfläche den Befehl auf, wenn sie gedrückt wird. Der Befehl in diesem Beispiel ist an die GiveBonus
Eigenschaft des ViewModels gebunden. Der Eigenschaftentyp muss die ICommand
Schnittstelle implementieren. Der Code sähe in etwa so aus:
public class EmployeeViewModel : INotifyPropertyChanged
{
public ICommand GiveBonus {get; private set;}
...
}
Die ICommand
-Schnittstelle umfasst eine Execute
-Methode, die aufgerufen wird, wenn auf die Schaltfläche geklickt wird. Auf diese Weise ist ICommand.Execute
eine direkte Ersetzung für den Button.Click
-Code zur Ereignisbehandlung.
Die vollständige ICommand
-Schnittstelle weist zwei weitere Methoden auf: CanExecute
und CanExecuteChanged
, die für die Ermittlung verwendet werden, ob ein Steuerelement als aktiviert oder deaktiviert angezeigt werden soll.
Eine Schaltfläche kann beispielsweise abgeblendet dargestellt werden, wenn CanExecute
FALSE zurückgibt.
So sieht die ICommand
Schnittstelle in C# aus:
public interface ICommand
{
bool CanExecute(object parameter);
void Execute(object parameter);
event EventHandler CanExecuteChanged;
}
Verwenden der Command-Klasse
Dieses Befehlsmuster ermöglicht eine saubere Trennung von UI-Verhalten und UI-Implementierung. Der Code kann jedoch komplexer werden, wenn Sie eine separate Klasse zum Implementieren jedes Ereignishandlers erstellen müssen.
Statt mehrere benutzerdefinierte Klassen zu erstellen, die die Schnittstelle implementieren, wird üblicherweise auf Command
oder Command<T>
zurückgegriffen. Diese Klassen implementieren ICommand
, stellen jedoch ihr Verhalten als Eigenschaften in Ihrem ViewModel bereit, das Sie festlegen können. Dadurch können Sie die zuvor beschriebene GiveBonus
-Eigenschaft vollständig in die ViewModel-Klasse implementieren:
public class EmployeeViewModel : INotifyPropertyChanged
{
public ICommand GiveBonus {get; private set;}
public EmployeeViewModel(Employee model)
{
GiveBonus = new Command(GiveBonusExecute, GiveBonusCanExecute)
}
void GiveBonusExecute()
{
//logic for giving bonus
}
bool GiveBonusCanExecute()
{
//logic for deciding if "give bonus" button should be enabled.
}
}
In diesem Code wird das Execute
-Verhalten von der Methode GiveBonusExecute
bereitgestellt. Und CanExecute
wird von GiveBonusCanExecute
bereitgestellt. Delegaten für diese Methoden werden an den Konstruktor Command
übergeben. Dieses Beispiel enthält keine Implementierung für CanExecuteChanged
.
Befehle mit Parametern
Die ICommand
Schnittstelle akzeptiert einen object
Parameter für die CanExecute
und Execute
-Methoden. .NET MAUI implementiert diese Schnittstelle ohne Typüberprüfung durch die Command
Klasse. Die Delegate, die Sie an den Befehl anfügen, müssen ihre eigene Typüberprüfung durchführen, um sicherzustellen, dass der richtige Parameter übergeben wird. .NET MAUI stellt außerdem die Command<T>
Implementierung bereit, in der Sie den erwarteten Parametertyp festlegen. Wenn Sie einen Befehl erstellen, der einen einzelnen Parametertyp akzeptiert, verwenden Sie Command<T>
.
.NET MAUI-Steuerelemente, die das Befehlsmuster implementieren, stellen die CommandParameter
Eigenschaft bereit. Durch Festlegen dieser Eigenschaft können Sie einen Parameter an den Befehl übergeben, wenn er mit Execute
aufgerufen wird, oder wenn er die CanExecute
Methode auf Status überprüft.
In diesem Beispiel wird der Zeichenfolgenwert 25 an den Befehl gesendet:
<Button Text="Give Bonus" Command="{Binding GiveBonus}" CommandParameter="25" />
Der Befehl müsste diesen Zeichenfolgenparameter interpretieren und konvertieren. Es gibt viele Möglichkeiten, einen stark typierten Parameter bereitzustellen.
Verwenden Sie anstelle der Attributsyntax zum Definieren von
CommandParameter
XAML-Elemente.<Button Text="Give Bonus" Command="{Binding GiveBonus}"> <Button.CommandParameter> <x:Int32>25</x:Int32> </Button.CommandParameter> </Button>
Binden Sie die
CommandParameter
an eine Instanz des richtigen Typs.Wenn die
CommandParameter
an den falschen Typ gebunden wird, wenden Sie einen Konverter an, um den Wert in den richtigen Typ zu konvertieren.