Verwenden von Befehlen in einer ViewModel-Komponente

Abgeschlossen

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.

Überprüfen Sie Ihr Wissen

1.

Was ist der Zweck der ICommand Schnittstelle?

2.

Wie können die Command oder Command<T> Klassen die Verwendung der ICommand Schnittstelle vereinfachen?

3.

Welche Rolle spielt die CommandParameter Eigenschaft in .NET MAUI-Steuerelementen?