Freigeben über


Überprüfen

Tipp

Diese Inhalte sind ein Auszug aus dem eBook „Enterprise Application Patterns Using .NET MAUI“, verfügbar unter .NET Docs oder als kostenlos herunterladbare PDF-Datei, die offline gelesen werden kann.

Enterprise Application Patterns Using .NET MAUI (Miniaturansicht eBook-Deckblatt).

Jede App, die Eingaben von Benutzern akzeptiert, sollte sicherstellen, dass die Eingabe gültig ist. Eine App könnte beispielsweise auf Eingaben prüfen, die nur Zeichen in einem bestimmten Bereich enthalten, eine bestimmte Länge haben oder einem bestimmten Format entsprechen. Ohne Validierung kann ein Benutzer Daten bereitstellen, die dazu führen, dass die App fehlschlägt. Eine ordnungsgemäße Validierung setzt die Geschäftsregeln durch und kann einen Angreifer daran hindern, bösartige Daten einzuschleusen.

Im Kontext des MVVM-Musters (Model-View-ViewModel) ist häufig ein Ansichtsmodell oder Modell erforderlich, um die Datenvalidierung durchzuführen und alle Validierungsfehler an die Ansicht zu melden, damit der Benutzer sie korrigieren kann. Die multiplattformfähige eShop-App führt eine synchrone clientseitige Validierung der Ansichtsmodelleigenschaften durch und benachrichtigt Benutzer und Benutzerinnen über Validierungsfehler, indem das Steuerelement hervorgehoben wird, das die ungültigen Daten enthält, und Fehlermeldungen angezeigt werden, die darüber informieren, warum die Daten ungültig sind. Die folgende Abbildung zeigt die Klassen, die an der Validierung in der multiplattformfähigen eShop-App beteiligt sind.

Validierungsklassen in der multiplattformfähigen eShop-App.

Ansichtsmodelleigenschaften, die eine Validierung erfordern, sind vom Typ ValidatableObject<T>, und jede ValidatableObject<T>-Instanz verfügt über Validierungsregeln, die ihrer Validations-Eigenschaft hinzugefügt wurden. Die Validierung wird über das Ansichtsmodell aufgerufen, indem die Validate-Methode der ValidatableObject<T>--Instanz aufgerufen wird, die die Validierungsregeln abruft und für die ValidatableObject<T>.Value-Eigenschaft ausführt. Alle Validierungsfehler werden in die Errors-Eigenschaft der ValidatableObject<T>-Instanz eingefügt, und die IsValid-Eigenschaft der ValidatableObject<T>-Instanz wird aktualisiert, um anzugeben, ob die Validierung erfolgreich war oder fehlgeschlagen ist. Im folgenden Code wird die Implementierung von ValidatableObject<T> gezeigt:

using CommunityToolkit.Mvvm.ComponentModel;
namespace eShop.Validations;
public class ValidatableObject<T> : ObservableObject, IValidity
{
    private IEnumerable<string> _errors;
    private bool _isValid;
    private T _value;
    public List<IValidationRule<T>> Validations { get; } = new();
    public IEnumerable<string> Errors
    {
        get => _errors;
        private set => SetProperty(ref _errors, value);
    }
    public bool IsValid
    {
        get => _isValid;
        private set => SetProperty(ref _isValid, value);
    }
    public T Value
    {
        get => _value;
        set => SetProperty(ref _value, value);
    }
    public ValidatableObject()
    {
        _isValid = true;
        _errors = Enumerable.Empty<string>();
    }
    public bool Validate()
    {
        Errors = Validations
            ?.Where(v => !v.Check(Value))
            ?.Select(v => v.ValidationMessage)
            ?.ToArray()
            ?? Enumerable.Empty<string>();
        IsValid = !Errors.Any();
        return IsValid;
    }
}

Eigenschaftsänderungsbenachrichtigungen werden von der ObservableObject-Klasse bereitgestellt. Daher kann ein Entry-Steuerelement an die IsValidEigenschaft der ValidatableObject<T>-Instanz in der Ansichtsmodellklasse gebunden werden, um benachrichtigt zu werden, ob die eingegebenen Daten gültig sind.

Angeben von Validierungsregeln

Validierungsregeln werden durch Erstellen einer Klasse angegeben, die von der IValidationRule<T>-Schnittstelle abgeleitet wird, was im folgenden Codebeispiel gezeigt wird:

public interface IValidationRule<T>
{
    string ValidationMessage { get; set; }
    bool Check(T value);
}

Diese Schnittstelle gibt an, dass eine Validierungsregelklasse eine boolesche Check-Methode bereitstellen muss, die zum Ausführen der erforderlichen Validierung verwendet wird, sowie eine ValidationMessage-Eigenschaft, deren Wert die Validierungsfehlermeldung ist, die angezeigt wird, wenn die Validierung fehlschlägt.

Das folgende Codebeispiel zeigt die IsNotNullOrEmptyRule<T>-Validierungsregel, die verwendet wird, um die Validierung des Benutzernamens und Kennworts durchzuführen, der bzw.das von Benutzern und Benutzerinnen für die LoginView eingegeben wird, wenn Pseudodienste in der multiplattformfähigen eShop-App verwendet werden:

public class IsNotNullOrEmptyRule<T> : IValidationRule<T>
{
    public string ValidationMessage { get; set; }

    public bool Check(T value) =>
        value is string str && !string.IsNullOrWhiteSpace(str);
}

Die Check-Methode gibt einen booleschen Wert zurück, der angibt, ob das Wertargument NULL bzw. leer ist oder nur aus Leerzeichen besteht.

Das folgende Codebeispiel zeigt eine Validierungsregel zum Überprüfen von E-Mail-Adressen, wird jedoch nicht von der multiplattformfähigen eShop-App verwendet:

public class EmailRule<T> : IValidationRule<T>
{
    private readonly Regex _regex = new(@"^([w.-]+)@([w-]+)((.(w){2,3})+)$");

    public string ValidationMessage { get; set; }

    public bool Check(T value) =>
        value is string str && _regex.IsMatch(str);
}

Die Check-Methode gibt einen booleschen Wert zurück, der angibt, ob das Value-Argument eine gültige E-Mail-Adresse ist. Dies wird erreicht, indem das Wertargument nach dem ersten Vorkommen des im Regex-Konstruktor angegebenen Musters für reguläre Ausdrücke durchsucht wird. Ob das Muster des regulären Ausdrucks in der Eingabezeichenfolge gefunden wurde, kann durch Abgleichen von value mit Regex.IsMatch überprüft werden.

Hinweis

Die Validierung von Eigenschaften kann manchmal abhängige Eigenschaften umfassen. Ein Beispiel für abhängige Eigenschaften ist, wenn die Menge der gültigen Werte für Eigenschaft A von dem bestimmten Wert abhängt, der in Eigenschaft B festgelegt wurde. Um zu prüfen, ob der Wert von Eigenschaft A einer der zulässigen Werte ist, müsste der Wert von Eigenschaft B abgerufen werden. Wenn sich der Wert von Eigenschaft B ändert, müsste außerdem die Eigenschaft A erneut validiert werden.

Hinzufügen von Validierungsregeln zu einer Eigenschaft

In der multiplattformfähigen eShop-App werden Ansichtsmodelleigenschaften, die eine Validierung erfordern, als Typ ValidatableObject<T> deklariert, wobei T der Typ der zu überprüfenden Daten ist. Das folgende Codebeispiel zeigt ein Beispiel für zwei solcher Eigenschaften:

public ValidatableObject<string> UserName { get; private set; }
public ValidatableObject<string> Password { get; private set; }

Damit Validierung durchgeführt wird, müssen der Validierungssammlung jeder ValidatableObject<T>-Instanz Validierungsregeln hinzugefügt werden, wie im folgenden Codebeispiel gezeigt:

private void AddValidations()
{
    UserName.Validations.Add(new IsNotNullOrEmptyRule<string> 
    { 
        ValidationMessage = "A username is required." 
    });

    Password.Validations.Add(new IsNotNullOrEmptyRule<string> 
    { 
        ValidationMessage = "A password is required." 
    });
}

Diese Methode fügt die IsNotNullOrEmptyRule<T>-Validierungsregel der Validations-Sammlung jeder ValidatableObject<T>-Instanz hinzu und gibt Werte für die ValidationMessage-Eigenschaft der Validierungsregel an, die die Validierungsfehlermeldung angibt, die angezeigt wird, wenn die Validierung fehlschlägt.

Auslösen von Validierung

Beim Validierungsansatz, der in der multiplattformfähigen eShop-App verwendet wird, kann die Validierung einer Eigenschaft manuell ausgelöst werden und automatisch ausgelöst werden, wenn sich eine Eigenschaft ändert.

Manuelles Auslösen der Validierung

Validierung kann manuell für eine Ansichtsmodelleigenschaft ausgelöst werden. Dies geschieht beispielsweise in der multiplattformfähigen eShop-App, wenn der Benutzer oder die Benutzerin bei Verwendung von Pseudodiensten auf die Schaltfläche Login für die LoginView tippt. Der Befehlsdelegat ruft die MockSignInAsync-Methode im LoginViewModel auf, wodurch die Validierung durch Ausführen der Validate-Methode aufgerufen wird.Dies wird im folgenden Codebeispiel gezeigt:

private bool Validate()
{
    bool isValidUser = ValidateUserName();
    bool isValidPassword = ValidatePassword();
    return isValidUser && isValidPassword;
}

private bool ValidateUserName()
{
    return _userName.Validate();
}

private bool ValidatePassword()
{
    return _password.Validate();
}

Die Validate-Methode führt die Validierung des Benutzernamens und des Kennworts durch, der bzw.das vom Benutzer für die LoginVieweingegeben wurde, indem die Validate-Methode für jede ValidatableObject<T>-Instanz aufgerufen wird. Im folgenden Codebeispiel wird die Validate-Methode aus der ValidatableObject<T>-Klasse gezeigt:

public bool Validate()
{
    Errors = _validations
        ?.Where(v => !v.Check(Value))
        ?.Select(v => v.ValidationMessage)
        ?.ToArray()
        ?? Enumerable.Empty<string>();

    IsValid = !Errors.Any();

    return IsValid;
}

Diese Methode ruft alle Validierungsregeln ab, die der Validations-Sammlung des Objekts hinzugefügt wurden. Die Check-Methode für jede abgerufene Validierungsregel wird ausgeführt, und der Wert der ValidationMessage-Eigenschaft für jede Validierungsregel, die die Daten nicht validieren kann, wird der Errors-Sammlung der ValidatableObject<T>-Instanz hinzugefügt. Schließlich wird die IsValid-Eigenschaft festgelegt, und ihr Wert wird an die aufrufende Methode zurückgegeben. Dieser Wert gibt an, ob die Validierung erfolgreich war oder fehlgeschlagen ist.

Auslösen der Validierung bei Änderung von Eigenschaften

Validierung wird auch automatisch ausgelöst, wenn sich eine gebundene Eigenschaft ändert. Wenn eine bidirektionale Bindung beispielsweise in der LoginView die UserName- oder Password-Eigenschaft festlegt, wird Validierung ausgelöst. Das folgende Codebeispiel veranschaulicht, wie dies erreicht wird:

<Entry Text="{Binding UserName.Value, Mode=TwoWay}">
    <Entry.Behaviors>
        <behaviors:EventToCommandBehavior
            EventName="TextChanged"
            Command="{Binding ValidateUserNameCommand}" />
    </Entry.Behaviors>
</Entry>

Das Entry-Steuerelement wird an die UserName.Value-Eigenschaft der ValidatableObject<T>-Instanz gebunden, und der Behaviors-Sammlung des Steuerelements wird eine EventToCommandBehavior-Instanz hinzugefügt. Dieses Verhalten führt ValidateUserNameCommand als Antwort auf das TextChanged-Ereignis aus, das für Entry ausgelöst wird, wenn sich der Text in Entry ändert. Der ValidateUserNameCommand-Delegat wiederum führt die ValidateUserName-Methode aus, die die Validate-Methode für die ValidatableObject<T>-Instanz ausführt. Daher wird jedes Mal, wenn der Benutzer ein Zeichen in das Entry-Steuerelement für den Benutzernamen eingibt, eine Validierung der eingegebenen Daten durchgeführt.

Anzeigen von Validierungsfehlern

Die multiplattformfähige eShop-App benachrichtigt Benutzer und Benutzerinnen über alle Validierungsfehler, indem das Steuerelement mit rotem Hintergrund hervorgehoben wird, das die ungültigen Daten enthält, und eine Fehlermeldung wird unterhalb des Steuerelements angezeigt, das die ungültigen Daten enthält. Sie informiert darüber, warum die Daten ungültig sind. Wenn die ungültigen Daten korrigiert werden, wechselt der Hintergrund wieder in den Standardzustand, und die Fehlermeldung wird entfernt. Die folgende Abbildung zeigt die LoginView in der multiplattformfähigen eShop-App, wenn Validierungsfehler vorliegen.

Anzeige von Validierungsfehlern während der Anmeldung.

Hervorheben eines Steuerelements, das ungültige Daten enthält

.NET MAUI bietet eine Reihe von Möglichkeiten zum Präsentieren von Validierungsinformationen für Endbenutzer. Eine der einfachsten Möglichkeiten ist jedoch die Verwendung von Triggers. Triggers bieten uns eine Möglichkeit, den Zustand unserer Steuerelemente basierend auf einer Ereignis- oder Datenänderung zu ändern (in der Regel für die Darstellung), die für ein Steuerelement auftritt. Zur Validierung verwenden wir einen DataTrigger, der auf Änderungen lauscht, die von einer gebundenen Eigenschaft ausgelöst werden, und auf die Änderungen reagiert. Die Entry-Steuerelemente für die LoginView werden mit dem folgenden Code eingerichtet:

<Entry Text="{Binding UserName.Value, Mode=TwoWay}">
    <Entry.Style>
        <OnPlatform x:TypeArguments="Style">
            <On Platform="iOS, Android" Value="{StaticResource EntryStyle}" />
            <On Platform="WinUI" Value="{StaticResource WinUIEntryStyle}" />
        </OnPlatform>
    </Entry.Style>
    <Entry.Behaviors>
        <mct:EventToCommandBehavior
            EventName="TextChanged"
            Command="{Binding ValidateCommand}" />
    </Entry.Behaviors>
    <Entry.Triggers>
        <DataTrigger 
            TargetType="Entry"
            Binding="{Binding UserName.IsValid}"
            Value="False">
            <Setter Property="BackgroundColor" Value="{StaticResource ErrorColor}" />
        </DataTrigger>
    </Entry.Triggers>
</Entry>

Der DataTrigger gibt die folgenden Eigenschaften an:

Eigenschaft BESCHREIBUNG
TargetType Der Steuerelementtyp, zu dem der Trigger gehört.
Binding Das Binding-Markup der Daten, das Änderungsbenachrichtigungen und den Wert für die Triggerbedingung bereitstellt.
Value Der Datenwert, der angegeben wird, wenn die Bedingung des Triggers erfüllt wurde.

Für diesen Entry wird auf Änderungen an der LoginViewModel.UserName.IsValid-Eigenschaft gelauscht. Jedes Mal, wenn diese Eigenschaft eine Änderung auslöst, wird der Wert mit der Value-Eigenschaft verglichen, die in DataTrigger festgelegt ist. Wenn die Werte gleich sind, ist die Triggerbedingung erfüllt, und alle für den DataTrigger bereitgestellten Setter-Objekte werden ausgeführt. Dieses Steuerelement verfügt über ein einzelnes Setter-Objekt, das die BackgroundColor-Eigenschaft in eine benutzerdefinierte Farbe aktualisiert, die mithilfe des StaticResource-Markups definiert wird. Wenn eine Trigger-Bedingung nicht mehr erfüllt wird, setzt das Steuerelement die vom Setter-Objekt festgelegten Eigenschaften in ihren vorherigen Zustand zurück. Weitere Informationen zu Triggersfinden Sie in der .NET MAUI-Dokumentation: Trigger.

Anzeigen von Fehlermeldungen

Die Benutzeroberfläche zeigt Validierungsfehlermeldungen in Label-Steuerelementen unter jedem Steuerelement an, dessen Daten die Validierung nicht bestanden haben. Das folgende Codebeispiel zeigt das Label an, das eine Validierungsfehlermeldung anzeigt, wenn der Benutzer keinen gültigen Benutzernamen eingegeben hat:

<Label
    Text="{Binding UserName.Errors, Converter={StaticResource FirstValidationErrorConverter}"
    Style="{StaticResource ValidationErrorLabelStyle}" />

Jedes Label-Steuerelement wird an die Errors-Eigenschaft des Ansichtsmodellobjekts gebunden, das validiert wird. Die Errors-Eigenschaft wird von der ValidatableObject<T>-Klasse bereitgestellt und ist vom Typ IEnumerable<string>. Da die Errors-Eigenschaft mehrere Validierungsfehler enthalten kann, wird die FirstValidationErrorConverter-Instanz verwendet, um den ersten Fehler aus der Sammlung zur Anzeige abzurufen.

Zusammenfassung

Die multiplattformfähige eShop-App führt eine synchrone clientseitige Validierung der Ansichtsmodelleigenschaften durch und benachrichtigt Benutzer und Benutzerinnen über Validierungsfehler, indem das Steuerelement hervorgehoben wird, das die ungültigen Daten enthält, und Fehlermeldungen angezeigt werden, die darüber informieren, warum die Daten ungültig sind.

Ansichtsmodelleigenschaften, die eine Validierung erfordern, sind vom Typ ValidatableObject<T>, und jede ValidatableObject<T>-Instanz verfügt über Validierungsregeln, die ihrer Validations-Eigenschaft hinzugefügt wurden. Die Validierung wird über das Ansichtsmodell aufgerufen, indem die Validate-Methode der ValidatableObject<T>--Instanz aufgerufen wird, die die Validierungsregeln abruft und für die ValidatableObject<T>-Werteigenschaft ausführt. Alle Validierungsfehler werden in die Errors-Eigenschaft der ValidatableObject<T>-Instanz eingefügt, und die IsValid-Eigenschaft der ValidatableObject<T>-Instanz wird aktualisiert, um anzugeben, ob die Validierung erfolgreich war oder fehlgeschlagen ist.