Erstellen einer konsistenten Benutzeroberfläche mithilfe von Stilen

Abgeschlossen

Ressourcen sind hervorragend geeignet, um hartcodierte, doppelte Werte im XAML-Markup zu vermeiden, deren Anwendung kann aber mühsam sein. Sie müssen jeden Eigenschaftswert einzeln zuweisen, wodurch die XAML überladen und unübersichtlich wird. In dieser Lerneinheit wird gezeigt, wie Sie mehrere Einstellungen in einem Stil gruppieren, um den Code übersichtlicher zu gestalten und ihn besser verwalten zu können.

Wie können Ressourcen zu unübersichtlicher XAML führen?

Eine Ressource bietet einen Wert für eine einzelne Eigenschaft. Die Verwendung vieler Ressourcen kann jedoch zu einer unübersichtlichen XAML führen. Nehmen Sie an, Sie möchten ein benutzerdefiniertes Erscheinungsbild für die Schaltflächen Ihrer App. Sie müssen zuerst Ressourcen für die Werte erstellen, die Sie benötigen. Dann wenden Sie die einzelnen Ressourcen auf alle Schaltflächen an. Der folgende Code zeigt, wie das XAML-Markup für zwei Schaltflächen aussehen könnte.

<Button
    Text = "OK"
    BackgroundColor = "{StaticResource highlightColor}"
    BorderColor = "{StaticResource borderColor}"
    BorderWidth = "{StaticResource borderWidth}"
    TextColor = "{StaticResource textColor}" />

<Button
    Text = "Cancel"
    BackgroundColor = "{StaticResource highlightColor}"
    BorderColor = "{StaticResource borderColor}"
    BorderWidth = "{StaticResource borderWidth}"
    TextColor = "{StaticResource textColor}" />

Beachten Sie, dass für jede der Schaltflächen die gleichen fünf Eigenschaften festgelegt sind. Durch die Verwendung von Ressourcen entfällt die Notwendigkeit wiederholter, fest programmierter Werte in vier von ihnen. Eine derartige XAML wird allerdings schnell schwer verständlich. Wenn Sie eine Vielzahl von Eigenschaften für jedes Steuerelement festlegen, kann es leicht passieren, dass eine davon versehentlich weggelassen wird, sodass die Darstellung der Steuerelemente inkonsistent wird. Die Lösung: Erstellen Sie einen Stil, der alle vier Eigenschaften gleichzeitig zuweist.

Was ist ein Setter?

Setter sind die wichtigsten Komponenten, die zum Erstellen von Stilen verwendet werden.

Ein Setter ist ein Container für ein Eigenschaft-Wert-Paar. Sie können sich einen Setter als Darstellung einer Zuweisungsanweisung vorstellen. Sie geben an, welche Eigenschaft zugewiesen und welcher Wert angewendet werden soll. In der Regel erstellen Sie Setter-Objekte in Ihrem XAML-Markup. Im folgenden Beispiel wird ein Setter-Objekt für die TextColor-Eigenschaft erstellt.

<Setter Property="TextColor" Value="White" />

Sie können in einem Setter wie im folgenden Code gezeigt eine Ressource für den Wert verwenden. Dieses Verfahren eignet sich sehr gut, wenn Sie den gleichen Wert in mehreren Settern verwenden möchten.

<Setter Property="TextColor" Value="{StaticResource textColor}" />

Hinweis

Der Eigenschaftswert, den Sie in einem Setter angeben, muss als bindbare Eigenschaft implementiert werden. Alle Eigenschaften von Steuerelementen in Xamarin.Forms, die mit dem Suffix Property enden, sind Eigenschaften, die gebunden werden können. Wenn Sie versuchen, eine Eigenschaft wie TextColor in einem Setter zu verwenden, muss für dieses Steuerelement eine entsprechende bindbare Eigenschaft namens TextColorProperty vorhanden sein. In der Praxis werden fast alle Eigenschaften, die Sie in Ihren Settern verwenden möchten, auf diese Weise implementiert.

Was ist ein Stil?

Ein Stil ist eine Sammlung von Settern für einen bestimmten Steuerelementtyp. .NET MAUI benötigt einen Zieltyp, um sicherstellen zu können, dass die Eigenschaften in Ihren Settern für den betreffenden Typ tatsächlich vorhanden sind.

Der folgende Code zeigt einen Stil, der die vier Werte aus dem vorherigen Beispiel kombiniert. Beachten Sie, dass TargetType auf Button festgelegt ist und alle Eigenschaften in den Settern Member der Button-Klasse sind. Sie können diesen Stil nicht für eine Beschriftung verwenden, da die Label-Klasse nicht die Eigenschaft BorderColor oder BorderWidth enthält.

<Style TargetType="Button">
    <Setter Property="BackgroundColor" Value="#2A84D3" />
    <Setter Property="BorderColor" Value="#1C5F9B" />
    <Setter Property="BorderWidth" Value="3" />
    <Setter Property="TextColor" Value="White" />
</Style>

Definieren eines Stils

In der Regel werden Stile als Ressourcen in einem ResourceDictionary-Objekt definiert. Mit einem Ressourcenverzeichnis lässt sich ein Stil problemlos in mehreren Steuerelementen auf der gleichen Seite oder sogar in der gesamten Anwendung verwenden. Der folgende Code zeigt, wie Sie einen Stil in einem Verzeichnis als Ressource definieren. Beachten Sie, dass dem Stil mit der x:Key-Eigenschaft ein Name zugewiesen wird. Durch Benennung eines Stils können Sie in XAML-Seiten darauf verweisen.

<ContentPage.Resources>
    <Style x:Key="MyButtonStyle" TargetType="Button">
        ...
    </Style>
</ContentPage.Resources>

Einen Stil anwenden

Sie fügen einen Stil an ein Steuerelement an, indem Sie den benannten Stil der Style-Eigenschaft zuweisen. Diese Zuweisung sorgt dafür, dass jedes der Setter-Objekte im Stil auf das Zielsteuerelement angewendet wird. Der folgende Code zeigt, wie ein Schaltflächenstil auf zwei Schaltflächen angewendet wird.

<Button Text="OK" Style="{StaticResource MyButtonStyle}" />
<Button Text="Cancel" Style="{StaticResource MyButtonStyle}" />

Im vorherigen Beispiel haben Sie die StaticResource-Markuperweiterung verwendet, um den Stil an die Steuerelemente anzufügen. Dieses Verfahren eignet sich sehr gut, wenn sich der Stil nicht zur Laufzeit ändern muss. Was aber, wenn Sie beispielsweise ein dynamisches Thema implementieren möchten, bei dem sich die Benutzeroberfläche ändern muss? In diesem Fall können Sie die DynamicResource-Markuperweiterung verwenden, um den Stil zu laden.

<Button Text="Cancel" Style="{DynamicResource MyButtonStyle}" />

DynamicResource ermittelt, ob die x:Key-Eigenschaft im Ressourcenverzeichnis ersetzt wurde. Wenn Sie Code schreiben, der einen neuen Stil mit demselben x:Key-Wert in das Ressourcenverzeichnis lädt, wird der neue Stil automatisch auf die Benutzeroberfläche angewendet.

Verwenden eines impliziten Stils für mehrere Steuerelemente

Nehmen Sie beispielsweise an, dass Ihre Benutzeroberfläche 50 Schaltflächen enthält und Sie auf alle den gleichen Stil anwenden möchten. Mit unseren bisherigen Kenntnissen müssten Sie die Style-Eigenschaft für jede Schaltfläche manuell zuweisen. Das ist nicht schwierig, aber mühsam.

Ein impliziter Stil ist ein Stil, dem Sie einem Ressourcenverzeichnis hinzufügen, ohne einen x:Key-Bezeichner anzugeben. Implizite Stile werden automatisch auf alle Steuerelemente des angegebenen TargetType-Objekts angewendet.

Der folgende Code zeigt das vorherige Beispiel mit Deklaration als impliziter Stil. Dieser Stil wird auf alle Schaltflächen auf der Seite angewendet.

<ContentPage.Resources>
    <Style TargetType="Button">
        <Setter Property="BackgroundColor" Value="Blue" />
        <Setter Property="BorderColor" Value="Navy" />
        ...
    </Style>
</ContentPage.Resources>

Wichtig

Der Abgleich impliziter Stile mit Steuerelementen erfordert eine exakte Übereinstimmung mit dem angegebenen TargetType. Steuerelement, die vom Zieltyp erben, empfangen die Stile nicht. Um geerbte Steuerelemente zu beeinflussen, können Sie das Style.ApplyToDerivedTypes-Attribut beim Definieren des Stils auf True festlegen. Wenn Sie beispielsweise einen Stil auf den Button-Typ anwenden und damit alle Schaltflächen, die von Button erben (z. B. ImageButton, RadioButton oder ein erstellter benutzerdefinierter Typ), beeinflussen möchten, können Sie eine solche Formatvorlage verwenden.

<ContentPage.Resources>
    <Style TargetType="Button"
           ApplyToDerivedTypes="True">
        <Setter Property="BackgroundColor" Value="Black" />
    </Style>
</ContentPage.Resources>

Überschreiben eines Stils

Sie können sich einen Stil als Gruppe von Standardwerten für Steuerelemente vorstellen. Ein vorhandener Stil könnte Ihren Anforderungen sehr nahe kommen, aber einen oder zwei Setter enthalten, die Sie nicht wollen. In diesem Fall können Sie den Stil anwenden und dann den Wert überschreiben, indem Sie Eigenschaften direkt festlegen. Die explizite Einstellung wird nach dem Stil angewendet, überschreibt daher den Wert im Stil.

Nehmen wir an, Sie möchten den folgenden Stil für verschiedene Schaltflächen auf Ihrer Seite verwenden.

<Style x:Key="MyButtonStyle" TargetType="Button">
    <Setter Property="BackgroundColor" Value="Blue" />
    <Setter Property="BorderRadius" Value="10" />
    <Setter Property="BorderWidth" Value="3" />
</Style>

Dieser Stil ist für die meisten Schaltflächen geeignet, mit Ausnahme der Schaltfläche zum Abbrechen, für die ein roter Hintergrund gewünscht ist. Sie können dieselbe Formatvorlage für die Cancel-Schaltfläche verwenden, wenn Sie auch die BackgroundColor-Eigenschaft direkt festlegen. Der folgende Code zeigt, wie die Farbeinstellung überschrieben wird.

<Button
    Text="Cancel"
    Style="{StaticResource MyButtonStyle}"
    BackgroundColor="Red"
    ... />

Verwenden eines Vorgängertyps

Nehmen wir an, Sie möchten eine benutzerdefinierte Hintergrundfarbe für Ihre Schaltflächen und Bezeichnungen verwenden. Sie können separate Stile für jeden Typ erstellen. Sie können auch einen Stil erstellen, für den TargetType auf VisualElement festgelegt ist. Dieses Verfahren funktioniert, da VisualElement eine Basisklasse für Button und Label ist.

Der folgende Code zeigt einen Stil, der eine Basisklasse verwendet, die auf zwei verschiedene abgeleitete Typen angewendet wird.

<Style x:Key="MyVisualElementStyle" TargetType="VisualElement">
    <Setter Property="BackgroundColor" Value="#2A84D3" />
</Style>
...
<Button Style="{StaticResource MyVisualElementStyle}" ... />
<Label Style="{StaticResource MyVisualElementStyle}" ... />

In diesem Beispiel wird der Stil über x:Key angegeben, und die Steuerelemente wenden den Stil explizit an. Hier funktioniert ein impliziter Stil nicht, weil TargetType für einen impliziten Stil exakt mit dem Steuerelementtyp übereinstimmen muss.

Verwenden von BasedOn zum Erben von einem Stil

Nehmen Sie an, Sie möchten ein einheitliches Erscheinungsbild für Ihre Benutzeroberfläche erzeugen. Sie beschließen, dass alle Steuerelemente eine einheitliche Hintergrundfarbe verwenden sollen. Die Einstellung der Hintergrundfarbe wird dann sehr wahrscheinlich in mehreren der Stile verwendet. Der folgende Code zeigt zwei Stile mit einem wiederholten Setter.

<Style x:Key="MyButtonStyle" TargetType="Button">
    <Setter Property="BackgroundColor" Value="Blue" />
    <Setter Property="BorderColor" Value="Navy" />
    <Setter Property="BorderWidth" Value="5" />
</Style>

<Style x:Key="MyEntryStyle" TargetType="Entry">
    <Setter Property="BackgroundColor" Value="Blue" />
    <Setter Property="TextColor" Value="White" />
</Style>

Sie können die Stilvererbung verwenden, um den doppelten Setter in einen Basisstil auszuklammern. Legen Sie zum Erstellen eines abgeleiteten Stils die BasedOn-Eigenschaft fest, um auf den Basisstil zu verweisen. Der neue Stil erbt alle Setter aus dem Basisstil. Der abgeleitete Stil kann auch neue Setter hinzufügen oder einen geerbten Setter durch einen Setter mit einem anderen Wert ersetzen.

Der folgende Code zeigt die vorherigen Beispielstile, die in eine Hierarchie umgestaltet wurden. Der gemeinsame Setter wird nur im Basisstil verwendet und nicht wiederholt. Beachten Sie, dass die StaticResource-Markuperweiterung verwendet wird, um den Basisstil zu finden. In dieser Situation können Sie DynamicResource nicht verwenden.

<Style x:Key="MyVisualElementStyle" TargetType="VisualElement">
    <Setter Property="BackgroundColor" Value="Blue" />
</Style>

<Style x:Key="MyButtonStyle" TargetType="Button" BasedOn="{StaticResource MyVisualElementStyle}">
    <Setter Property="BorderColor" Value="Navy" />
    <Setter Property="BorderWidth" Value="5" />
</Style>

<Style x:Key="MyEntryStyle" TargetType="Entry" BasedOn="{StaticResource MyVisualElementStyle}">
    <Setter Property="TextColor" Value="White" />
</Style>

Die TargetType-Werte des Basisstils und der abgeleiteten Stile müssen kompatibel sein. Damit die Stile kompatibel sind, müssen sie entweder über dieselbe TargetType-Eigenschaft verfügen, oder der TargetType des abgeleiteten Stils ist eine untergeordnete Eigenschaft von TargetType des Basisstils.

Wissensbeurteilung

1.

Warum würden Sie einen Stil in einem ResourceDictionary definieren?