Visueller Zustand
Der .NET Multi-Platform App UI (.NET MAUI) Visual State Manager bietet eine strukturierte Möglichkeit, visuelle Änderungen an der Benutzeroberfläche vom Code aus vorzunehmen. In den meisten Fällen wird die Benutzeroberfläche einer Anwendung in XAML definiert, und diese XAML kann Markup enthalten, das beschreibt, wie der Visual State Manager die visuelle Darstellung der Benutzeroberfläche beeinflusst.
Der Visual State Manager führt das Konzept der visuellen Zustände ein. Eine .NET MAUI-Ansicht, wie etwa Button, kann je nach ihrem zugrunde liegenden Status – ob sie deaktiviert oder gedrückt ist oder den Eingabefokus hat – verschiedene visuelle Erscheinungsbilder haben. Dies sind die Status der Schaltfläche. Visuelle Zustände werden in visuellen Zustandsgruppen gesammelt. Alle visuellen Status innerhalb einer visuellen Statusgruppe schließen sich gegenseitig aus. Sowohl visuelle Status als auch visuelle Statusgruppen werden durch einfache Textzeichenfolgen gekennzeichnet.
Der .NET MAUI Visual State Manager definiert eine visuelle Statusgruppe namens CommonStates
mit den folgenden visuellen Status:
- Normal
- Disabled
- Fokus
- Ausgewählt
- PointerOver
Die visuellen Zustände Normal
, Disabled
, Focused
und PointerOver
werden von allen Klassen unterstützt, die von VisualElement abgeleitet sind, der Basisklasse für View und Page. Darüber hinaus können Sie auch Ihre eigenen visuellen Zustandsgruppen und visuellen Zustände definieren.
Der Vorteil der Verwendung des Visual State Managers zur Definition des Erscheinungsbildes gegenüber dem direkten Zugriff auf visuelle Elemente über Code-Behind ist, dass Sie die Reaktion der visuellen Elemente auf verschiedene Status vollständig in XAML steuern können, wodurch das gesamte UI-Design an einem Ort bleibt.
Hinweis
Auslöser können auch Änderungen an der visuellen Darstellung der Benutzeroberfläche vornehmen, die auf Änderungen der Eigenschaften einer Ansicht oder dem Auslösen von Ereignissen basieren. Die Verwendung von Auslösern für verschiedene Kombinationen dieser Änderungen kann jedoch verwirrend werden. Mit dem Visual State Manager schließen sich die visuellen Zustände innerhalb einer visuellen Zustandsgruppe immer gegenseitig aus. Zu jedem Zeitpunkt ist nur ein Zustand in jeder Gruppe der aktuelle Zustand.
Gängige visuelle Zustände
Mit dem Visual State Manager können Sie Markups in Ihre XAML-Datei einfügen, die das visuelle Erscheinungsbild einer Ansicht ändern, wenn die Ansicht normal oder deaktiviert ist, den Eingabefokus hat, ausgewählt ist oder der Mauszeiger über ihr schwebt, aber nicht gedrückt ist. Diese werden als gänige Zustände bezeichnet.
Angenommen, Sie haben eine Entry-Ansicht auf Ihrer Seite und möchten, dass sich das visuelle Erscheinungsbild der Entry-Ansicht auf folgende Weise ändert:
- Entry sollte einen rosa Hintergrund haben, wenn der Entry deaktiviert ist.
- Entry sollte normalerweise einen kalkfarbenen Hintergrund haben.
- Entry sollte sich auf das Doppelte seiner normalen Höhe ausdehnen, wenn er den Eingabefokus hat.
- Entry sollte einen hellblauen Hintergrund haben, wenn der Mauszeiger darüber schwebt, aber nicht gedrückt ist.
Sie können das Visual State Manager Markup an eine einzelne Ansicht anhängen oder es in einem Stil definieren, wenn es für mehrere Ansichten gilt.
Definition visueller Status in einer Ansicht
Die VisualStateManager
-Klasse definiert eine angehängte Eigenschaft VisualStateGroups
, die verwendet wird, um visuelle Zustände an eine Ansicht anzuhängen. Die VisualStateGroups
-Eigenschaft ist vom Typ VisualStateGroupList
, der eine Sammlung von VisualStateGroup
-Objekten ist. Daher ist das untergeordnete Element der angehängten Eigenschaft VisualStateManager.VisualStateGroups
ein VisualStateGroup
-Objekt. Dieses Objekt definiert ein x:Name
-Attribut, das den Namen der Gruppe angibt. Alternativ dazu definiert die Klasse VisualStateGroup
eine Eigenschaft Name
, die Sie stattdessen verwenden können. Weitere Informationen zu angefügten Eigenschaften finden Sie unter Angefügte Eigenschaften.
Die Klasse VisualStateGroup
definiert eine Eigenschaft namens States
, die eine Sammlung von VisualState-Objekten ist. States
ist die Inhaltseigenschaft der Klasse VisualStateGroups
, so dass Sie die VisualState-Objekte als untergeordnete Elemente der Klasse VisualStateGroup
einschließen können. Jedes VisualState-Objekt sollte mit x:Name
oder Name
gekennzeichnet werden.
Die Klasse VisualState definiert eine Eigenschaft namens Setters
, die eine Sammlung von Setter-Objekten ist. Dies sind die gleichen Setter-Objekte, die Sie in einem Style-Objekt verwenden. Setters
ist nicht die Inhaltseigenschaft von VisualState, daher ist es notwendig, Eigenschaftselement-Tags für die Setters
-Eigenschaft einzufügen. Setter Objekte sollten als untergeordnete Elemente von Setters
eingefügt werden. Jedes Setter-Objekt gibt den Wert einer Eigenschaft an, wenn dieser Zustand aktuell ist. Jede Eigenschaft, auf die von einem Setter-Objekt verwiesen wird, muss durch eine bindungsfähige Eigenschaft unterstützt werden.
Wichtig
Damit die Setter-Objekte für den visuellen Zustand korrekt funktionieren, muss ein VisualStateGroup
-Objekt ein VisualState-Objekt für den Normal
-Zustand enthalten. Wenn dieser visuelle Status keine Setter-Objekte enthält, sollte er als leerer visueller Status (<VisualState Name="Normal" />
) eingeschlossen werden.
Das folgende Beispiel zeigt visuelle Status, die für einen Entry definiert sind:
<Entry FontSize="18">
<VisualStateManager.VisualStateGroups>
<VisualStateGroupList>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Lime" />
</VisualState.Setters>
</VisualState>
<VisualState Name="Focused">
<VisualState.Setters>
<Setter Property="FontSize" Value="36" />
</VisualState.Setters>
</VisualState>
<VisualState Name="Disabled">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Pink" />
</VisualState.Setters>
</VisualState>
<VisualState Name="PointerOver">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="LightBlue" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</VisualStateManager.VisualStateGroups>
</Entry>
Der folgende Screenshot zeigt den Entry in seinen vier definierten visuellen Zuständen:
Wenn sich Entry im Zustand Normal
befindet, ist sein Hintergrund hellgrün. Wenn Entry den Eingabefokus erhält, verdoppelt sich die Schriftgröße. Wenn Entry deaktiviert wird, wird der Hintergrund rosa. Entry behält seinen hellgrünen Hintergrund nicht bei, wenn er den Eingabefokus erhält. Wenn der Mauszeiger über dem Entry schwebt, aber nicht gedrückt wird, wird der Entry-Hintergrund hellblau. Wenn der Visual State Manager zwischen den visuellen Zuständen wechselt, werden die im vorherigen Zustand eingestellten Eigenschaften aufgehoben. Daher schließen sich die visuellen Status gegenseitig aus.
Wenn das Entry im Status Focused
einen hellen Hintergrund haben soll, fügen Sie ein weiteres Setter zu diesem visuellen Status hinzu:
<VisualState Name="Focused">
<VisualState.Setters>
<Setter Property="FontSize" Value="36" />
<Setter Property="BackgroundColor" Value="Lime" />
</VisualState.Setters>
</VisualState>
Visuelle Zustände in einem Stil definieren
Oft ist es notwendig, dieselben visuellen Zustände in zwei oder mehr Ansichten gemeinsam zu nutzen. In diesem Szenario können die visuellen Zustände in einem Style definiert werden. Dies kann durch Hinzufügen eines Setter-Objekts für die VisualStateManager.VisualStateGroups
-Eigenschaft erreicht werden. Die Inhaltseigenschaft für das Setter-Objekt ist seine Value
-Eigenschaft, die daher als untergeordnetes Objekt des Setter-Objekts angegeben werden kann. Die VisualStateGroups
-Eigenschaft ist vom Typ VisualStateGroupList
, und so ist das untergeordnete Objekt des Setter-Objekts ein VisualStateGroupList
, dem ein VisualStateGroup
hinzugefügt werden kann, das VisualState-Objekte enthält.
Das folgende Beispiel zeigt einen impliziten Stil für einen Entry, der die gemeinsamen visuellen Status definiert:
<Style TargetType="Entry">
<Setter Property="FontSize" Value="18" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Lime" />
</VisualState.Setters>
</VisualState>
<VisualState Name="Focused">
<VisualState.Setters>
<Setter Property="FontSize" Value="36" />
<Setter Property="BackgroundColor" Value="Lime" />
</VisualState.Setters>
</VisualState>
<VisualState Name="Disabled">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Pink" />
</VisualState.Setters>
</VisualState>
<VisualState Name="PointerOver">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="LightBlue" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
Wenn dieser Stil in ein Ressourcenwörterbuch auf Seitenebene aufgenommen wird, wird das Style-Objekt auf alle Entry-Objekte auf der Seite angewendet. Daher reagieren alle Entry-Objekte auf der Seite in gleicher Weise auf ihre visuellen Status.
Visuelle Zustände in .NET MAUI
In der folgenden Tabelle sind die visuellen Zustände aufgeführt, die in .NET MAUI definiert sind:
Klasse | Zustände | Weitere Informationen |
---|---|---|
Button | Pressed |
Visuelle Zustände der Schaltfläche |
CarouselView | DefaultItem , CurrentItem , PreviousItem , NextItem |
CarouselView: visuelle Zustände |
CheckBox | IsChecked |
CheckBox: visuelle Zuständex |
CollectionView | Selected |
CollectionView: visuelle Zustände |
ImageButton | Pressed |
ImageButton: visuelle Zustände |
RadioButton | Checked , Unchecked |
RadioButton: visuelle Status |
Switch | On , Off |
Switch: visuelle Zustände |
VisualElement | Normal , Disabled , Focused , PointerOver |
Allgemeine Status |
Festlegen des Zustands für mehrere Elemente
In den vorangegangenen Beispielen wurden visuelle Status einzelnen Elementen beigefügt und auf diese angewendet. Es ist jedoch auch möglich, visuelle Status zu erstellen, die an ein einzelnes Element gebunden sind, aber Eigenschaften für andere Elemente innerhalb desselben Bereichs festlegen. Dadurch wird vermieden, dass die visuellen Status für jedes Element, auf das die Zustände wirken, wiederholt werden müssen.
Der Setter-Typ hat eine TargetName
-Eigenschaft vom Typ string
, die das Zielobjekt darstellt, das der Setter für einen visuellen Zustand manipulieren wird. Wenn die Eigenschaft TargetName
definiert ist, setzt Setter die Property
des in TargetName
definierten Objekts auf Value
:
<Setter TargetName="label"
Property="Label.TextColor"
Value="Red" />
In diesem Beispiel wird die Eigenschaft TextColor
eines Label namens label
auf Red
gesetzt. Wenn Sie die Eigenschaft TargetName
einstellen, müssen Sie den vollständigen Pfad zur Eigenschaft in Property
angeben. Um die Eigenschaft TextColor
auf Label zu setzen, wird daher Property
als Label.TextColor
angegeben.
Hinweis
Jede Eigenschaft, auf die von einem Setter-Objekt verwiesen wird, muss durch eine bindungsfähige Eigenschaft unterstützt werden.
Das folgende Beispiel zeigt, wie der Zustand mehrerer Objekte über eine einzige visuelle Zustandsgruppe festgelegt werden kann:
<StackLayout>
<Label Text="What is the capital of France?" />
<Entry x:Name="entry"
Placeholder="Enter answer" />
<Button Text="Reveal answer">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal" />
<VisualState Name="Pressed">
<VisualState.Setters>
<Setter Property="Scale"
Value="0.8" />
<Setter TargetName="entry"
Property="Entry.Text"
Value="Paris" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Button>
</StackLayout>
In diesem Beispiel ist der Zustand Normal
aktiv, wenn die Taste Button nicht gedrückt wird, und eine Antwort kann in die Taste Entry eingegeben werden. Der Status Pressed
wird aktiv, wenn die Taste Button gedrückt wird, und legt fest, dass seine Eigenschaft Scale
vom Standardwert 1 in 0,8 geändert wird. Außerdem wird die Entry mit dem Namen entry
mit der Eigenschaft Text
auf Paris gesetzt. Das Ergebnis ist also, dass die Button beim Drücken etwas kleiner skaliert wird und die Entry Paris anzeigt:
Wenn die Button dann losgelassen wird, wird sie auf ihren Standardwert von 1 zurückgesetzt, und die Entry zeigt jeden zuvor eingegebenen Text an.
Wichtig
Eigenschaftspfade werden in Setter-Elementen, die die TargetName
-Eigenschaft angeben, nicht unterstützt.
Definieren benutzerdefinierter visueller Status
Benutzerdefinierte visuelle Status können implementiert werden, indem man sie so definiert, wie man visuelle Status für die allgemeinen Status definieren würde, jedoch mit Namen Ihrer Wahl, und dann die Methode VisualStateManager.GoToState
aufruft, um einen Status zu aktivieren.
Das folgende Beispiel zeigt, wie Sie den Visual State Manager für die Eingabevalidierung verwenden:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="VsmDemos.VsmValidationPage"
Title="VSM Validation">
<StackLayout x:Name="stackLayout"
Padding="10, 10">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="ValidityStates">
<VisualState Name="Valid">
<VisualState.Setters>
<Setter TargetName="helpLabel"
Property="Label.TextColor"
Value="Transparent" />
<Setter TargetName="entry"
Property="Entry.BackgroundColor"
Value="Lime" />
</VisualState.Setters>
</VisualState>
<VisualState Name="Invalid">
<VisualState.Setters>
<Setter TargetName="entry"
Property="Entry.BackgroundColor"
Value="Pink" />
<Setter TargetName="submitButton"
Property="Button.IsEnabled"
Value="False" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Label Text="Enter a U.S. phone number:"
FontSize="18" />
<Entry x:Name="entry"
Placeholder="555-555-5555"
FontSize="18"
Margin="30, 0, 0, 0"
TextChanged="OnTextChanged" />
<Label x:Name="helpLabel"
Text="Phone number must be of the form 555-555-5555, and not begin with a 0 or 1" />
<Button x:Name="submitButton"
Text="Submit"
FontSize="18"
Margin="0, 20"
VerticalOptions="Center"
HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
In diesem Beispiel sind visuelle Zustände an StackLayout angehängt, und es gibt zwei sich gegenseitig ausschließende Zustände namens Valid
und Invalid
. Wenn Entry keine gültige Telefonnummer enthält, dann ist der aktuelle Status Invalid
, und somit hat Entry einen rosa Hintergrund, das zweite Label ist sichtbar und Button ist deaktiviert. Wenn eine gültige Rufnummer eingegeben wird, wird der aktuelle Zustand zu Valid
. Das Entry erhält einen hellgrünen Hintergrund, das zweite Label verschwindet, und Button ist jetzt aktiviert:
Die Code-Behind-Datei ist für die Verarbeitung des TextChanged
-Ereignisses von Entry verantwortlich. Der Handler verwendet einen regulären Ausdruck, um festzustellen, ob die Eingabezeichenfolge gültig ist oder nicht. Die Methode GoToState
in der Code-Behind-Datei ruft die statische Methode VisualStateManager.GoToState
des Objekts StackLayout auf:
public partial class VsmValidationPage : ContentPage
{
public VsmValidationPage()
{
InitializeComponent();
GoToState(false);
}
void OnTextChanged(object sender, TextChangedEventArgs args)
{
bool isValid = Regex.IsMatch(args.NewTextValue, @"^[2-9]\d{2}-\d{3}-\d{4}$");
GoToState(isValid);
}
void GoToState(bool isValid)
{
string visualState = isValid ? "Valid" : "Invalid";
VisualStateManager.GoToState(stackLayout, visualState);
}
}
In diesem Beispiel wird die Methode GoToState
vom Konstruktor aus aufgerufen, um den Zustand zu initialisieren. Es sollte immer einen aktuellen Stand geben. Die Code-Behind-Datei ruft dann VisualStateManager.GoToState
mit einem Zustandsnamen für das Objekt auf, das die visuellen Zustände definiert.
Auslöser visueller Status
Visuelle Status unterstützen Statusauslöser, bei denen es sich um eine spezielle Gruppe von Auslösern handelt, die die Bedingungen festlegen, unter denen ein VisualState angewendet werden soll.
Zustandstrigger werden der Sammlung StateTriggers eines VisualState hinzugefügt. Diese Sammlung kann Trigger mit einem oder mehreren Zustandstriggern enthalten. Ein VisualState wird angewendet, wenn alle Zustandstrigger in der Sammlung aktiv sind.
Bei Verwendung von Zustandstriggern zur Steuerung visueller Zustände verwendet .NET MAUI die folgenden Prioritätsregeln, um zu bestimmen, welcher Trigger (und welches entsprechende VisualState) aktiv ist:
- Alle von StateTriggerBase abgeleiteten Trigger.
- Ein AdaptiveTrigger, der aktiviert wird, da die Bedingung MinWindowWidth erfüllt ist.
- Ein AdaptiveTrigger, der aktiviert wird, da die Bedingung MinWindowHeight erfüllt ist.
Wenn mehrere Trigger gleichzeitig aktiv sind (z. B. zwei benutzerdefinierte Trigger), hat der erste im Markup deklarierte Trigger Vorrang.
Weitere Informationen zu Zustandstriggern finden Sie unter Zustandstrigger.