XAML-Formatvorlagen

Sie können die Darstellung Ihrer Apps auf vielfältige Weise mithilfe des XAML-Frameworks anpassen. Mit Stilen können Sie Steuerelementeigenschaften festlegen und diese Einstellungen für eine einheitliche Darstellung über mehrere Steuerelemente hinweg wiederverwenden.

Stilgrundlagen

Verwenden Sie Formatvorlagen, um visuelle Eigenschafteneinstellungen in wiederverwendbare Ressourcen zu extrahieren. Dieses Beispiel zeigt drei Schaltflächen mit einem Stil, der die Eigenschaften BorderBrush, BorderThickness und Foreground festlegt. Wenn Sie eine Formatvorlage anwenden, können Sie festlegen, dass die Steuerelemente gleich angezeigt werden, ohne diese Eigenschaften für jedes Steuerelement separat festlegen zu müssen.

Screenshot der drei formatierten, nebeneinander angeordneten Schaltflächen.

Sie können eine Formatvorlage inline im XAML für ein Steuerelement oder als wiederverwendbare Ressource definieren. Definieren Sie Ressourcen in der XAML-Datei einer einzelnen Seite, in der Datei "App.xaml" oder in einer separaten XAML-Datei des Ressourcenwörterbuchs. Eine XAML-Datei des Ressourcenwörterbuchs kann über Apps hinweg freigegeben werden, und mehrere Ressourcenwörterbücher können in einer einzelnen App zusammengeführt werden. Wo die Ressource definiert ist, bestimmt den Bereich, in dem sie verwendet werden kann. Ressourcen auf Seitenebene sind nur auf der Seite verfügbar, auf der sie definiert sind. Wenn Ressourcen mit demselben Schlüssel sowohl in "App.xaml" als auch auf einer Seite definiert sind, überschreibt die Ressource auf der Seite die Ressource in "App.xaml". Wenn eine Ressource in einer separaten Ressourcenwörterbuchdatei definiert ist, wird ihr Bereich durch den Ort bestimmt, an dem auf das Ressourcenwörterbuch verwiesen wird.

In der Style-Definition benötigen wir ein TargetType-Attribut und eine Auflistung mit einem oder mehreren Setter-Elementen. Das TargetType-Attribut ist eine Zeichenfolge, die einen FrameworkElement-Typ angibt, auf den der Stil angewendet werden soll. Der TargetType-Wert muss einen FrameworkElement-abgeleiteten Typ angeben, der durch die Windows-Runtime definiert wird, oder einen benutzerdefinierten Typ, der in einer referenzierten Assembly verfügbar ist. Wenn Sie versuchen, eine Formatvorlage auf ein Steuerelement anzuwenden und der Typ des Steuerelements nicht mit dem TargetType-Attribut der Formatvorlage übereinstimmt, die Sie anwenden möchten, tritt eine Ausnahme auf.

Jedes Setter-Element benötigt eine Property und einen Value. Diese Eigenschafteneinstellungen geben an, auf welche Steuerelementeigenschaft die Einstellung angewendet wird, und den Wert, der für diese Eigenschaft festgelegt werden soll. Sie können Setter.Value entweder mit Attribut- oder Eigenschaftselementsyntax festlegen. Das XAML zeigt die Formatvorlage, die auf die zuvor angezeigten Schaltflächen angewendet wurde. In diesem XAML-Code verwenden die ersten beiden Setter-Elemente Attributsyntax, aber der letzte Setter (für die BorderBrush-Eigenschaft) verwendet Eigenschaftselementsyntax. Im Beispiel wird nicht das x:Key attribute-Attribut verwendet, sodass die Formatvorlage implizit auf die Schaltflächen angewendet wird. Das Anwenden von Stilen, implizit oder explizit, wird im nächsten Abschnitt erläutert.

<Page.Resources>
    <Style TargetType="Button">
        <Setter Property="BorderThickness" Value="5" />
        <Setter Property="Foreground" Value="Black" />
        <Setter Property="BorderBrush" >
            <Setter.Value>
                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                    <GradientStop Color="Yellow" Offset="0.0" />
                    <GradientStop Color="Red" Offset="0.25" />
                    <GradientStop Color="Blue" Offset="0.75" />
                    <GradientStop Color="LimeGreen" Offset="1.0" />
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
    </Style>
</Page.Resources>

<StackPanel Orientation="Horizontal">
    <Button Content="Button"/>
    <Button Content="Button"/>
    <Button Content="Button"/>
</StackPanel>

Anwenden einer impliziten oder expliziten Formatvorlage

Wenn Sie einen Stil als Ressource definieren, gibt es zwei Möglichkeiten, ihn auf Ihre Steuerelementen anzuwenden:

Wenn ein Stil ein x:Key-Attribut enthält, können Sie ihn nur auf Steuerelemente anwenden, indem Sie die Style-Eigenschaft des Steuerelements auf den Stilschlüssel festlegen. Im Gegensatz dazu wird eine Formatvorlage ohne ein x:Key-Attribut automatisch auf jedes Steuerelement des Zieltyps angewendet, das andernfalls keine explizite Formatvorlageneinstellung aufweist.

Hier sind zwei Schaltflächen, die implizite und explizite Stile veranschaulichen.

Implizit und explizit formatierte Schaltflächen.

In diesem Beispiel besitzt der erste Stil ein x:Key-Attribut, und der Zieltyp ist Button. Die Style-Eigenschaft der ersten Schaltfläche wird auf diesen Schlüssel festgelegt, sodass der Stil explizit angewendet wird. Die zweite Formatvorlage wird implizit auf die zweite Schaltfläche angewendet, da deren Zieltyp Button lautet und die Formatvorlage kein x:Key-Attribut hat.

<Page.Resources>
    <Style x:Key="PurpleStyle" TargetType="Button">
        <Setter Property="FontFamily" Value="Segoe UI"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="Foreground" Value="Purple"/>
    </Style>

    <Style TargetType="Button">
        <Setter Property="FontFamily" Value="Segoe UI"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="RenderTransform">
            <Setter.Value>
                <RotateTransform Angle="25"/>
            </Setter.Value>
        </Setter>
        <Setter Property="BorderBrush" Value="Green"/>
        <Setter Property="BorderThickness" Value="2"/>
        <Setter Property="Foreground" Value="Green"/>
    </Style>
</Page.Resources>

<Grid x:Name="LayoutRoot">
    <Button Content="Button" Style="{StaticResource PurpleStyle}"/>
    <Button Content="Button"/>
</Grid>

Basierend auf Formatvorlagen verwenden

Damit Formatvorlagen einfacher zu verwalten sind und die Wiederverwendung von Formatvorlagen optimiert werden kann, können Sie Formatvorlagen erstellen, die von anderen Formatvorlagen erben. Verwenden Sie die BasedOn-Eigenschaft, um abgeleitete Stile zu erstellen. Formatvorlagen, die von anderen Formatvorlagen erben, müssen auf denselben Steuerelementtyp oder ein Steuerelement abzielen, das von dem Typ abgeleitet ist, auf den die Basisformatvorlage abzielt. Beispielsweise, wenn ein Basisstil auf ContentControlabzielt, können die darauf basierenden Stile auf ContentControl oder auf von ContentControl abgeleitete Typen abzielen, wie z. B. Button und ScrollViewer. Wenn in der formatbasierten Vorlage kein Wert festgelegt wird, wird er von der Basisformatvorlage geerbt. Um einen Wert aus der Basisformatvorlage zu ändern, überschreibt die formatbasierte Vorlage diesen Wert. Das nächste Beispiel zeigt einen Button und ein CheckBox mit Stilen, die von demselben Basisstil abgeleitet sind.

Formatierte Schaltflächen, die formatbasierte Vorlagen verwenden

Der Basisstil hat als Ziel ContentControl. Er legt die Height-Eigenschaft und die Width-Eigenschaft fest. Die von diesem Stil abgeleiteten Stile haben als Ziel CheckBox und Button, die von ContentControl abgeleitet sind. Die abgeleiteten Stile legen andere Farben für die BorderBrush-Eigenschaft und die Foreground-Eigenschaft fest. (Normalerweise setzen Sie keinen Rahmen um eine CheckBox. Hier dient es dazu, die Auswirkungen der Formatvorlage zu zeigen.)

<Page.Resources>
    <Style x:Key="BasicStyle" TargetType="ContentControl">
        <Setter Property="Width" Value="130" />
        <Setter Property="Height" Value="30" />
    </Style>

    <Style x:Key="ButtonStyle" TargetType="Button"
           BasedOn="{StaticResource BasicStyle}">
        <Setter Property="BorderBrush" Value="Orange" />
        <Setter Property="BorderThickness" Value="2" />
        <Setter Property="Foreground" Value="Red" />
    </Style>

    <Style x:Key="CheckBoxStyle" TargetType="CheckBox"
           BasedOn="{StaticResource BasicStyle}">
        <Setter Property="BorderBrush" Value="Blue" />
        <Setter Property="BorderThickness" Value="2" />
        <Setter Property="Foreground" Value="Green" />
    </Style>
</Page.Resources>

<StackPanel>
    <Button Content="Button" Style="{StaticResource ButtonStyle}" Margin="0,10"/>
    <CheckBox Content="CheckBox" Style="{StaticResource CheckBoxStyle}"/>
</StackPanel>

Leichtgewichtige Gestaltung

Das Überschreiben der Systempinsel geschieht gewöhnlich auf App- oder Seitenebene, und in keinem Fall wirkt sich die Farbüberschreibung auf alle Steuerelemente aus, die auf diesen Pinsel verweisen – und in XAML können zahlreiche Steuerelemente auf denselben Pinsel verweisen.

Screenshot von zwei Schaltflächen: eine im Ruhezustand und eine mit angewendeter einfacher Formatierung.

<Page.Resources>
    <ResourceDictionary>
        <ResourceDictionary.ThemeDictionaries>
            <ResourceDictionary x:Key="Light">
                 <SolidColorBrush x:Key="ButtonBackground" Color="Transparent"/>
                 <SolidColorBrush x:Key="ButtonForeground" Color="MediumSlateBlue"/>
                 <SolidColorBrush x:Key="ButtonBorderBrush" Color="MediumSlateBlue"/>
            </ResourceDictionary>
        </ResourceDictionary.ThemeDictionaries>
    </ResourceDictionary>
</Page.Resources>

Für Zustände wie PointerOver (Maus wird über die Schaltfläche bewegt), PointerPressed (Schaltfläche wurde aufgerufen) oder Deaktiviert (Mit der Schaltfläche ist keine Interaktion möglich). Diese Endungen werden an die ursprünglichen einfachen Formatierungsnamen angefügt: ButtonBackgroundPointerOver, ButtonForegroundPressed, ButtonBorderBrushDisabled usw. Durch die Änderung dieser Pinsel wird sichergestellt, dass die Farbe Ihrer Steuerelemente dem Design Ihrer App entspricht.

Wenn Sie diese Pinselüberschreibungen auf der App.Resources-Ebene platzieren, werden alle Schaltflächen innerhalb der gesamten App und nicht auf einer einzelnen Seite geändert.

Formatieren pro Steuerelement

In anderen Fällen ist es wünschenswert, ein einzelnes Steuerelement auf einer Seite so zu ändern, dass es auf eine bestimmte Weise aussieht, ohne andere Versionen dieses Steuerelements zu verändern.

Screenshot von drei formatierten, übereinander gestapelt angeordneten Schaltflächen.

<CheckBox Content="Normal CheckBox" Margin="5"/>
<CheckBox Content="Special CheckBox" Margin="5">
    <CheckBox.Resources>
        <ResourceDictionary>
            <ResourceDictionary.ThemeDictionaries>
                <ResourceDictionary x:Key="Light">
                    <SolidColorBrush x:Key="CheckBoxForegroundUnchecked"
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxForegroundChecked"
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxCheckGlyphForegroundChecked"
                        Color="White"/>
                    <SolidColorBrush x:Key="CheckBoxCheckBackgroundStrokeChecked"  
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxCheckBackgroundFillChecked"
                        Color="Purple"/>
                </ResourceDictionary>
            </ResourceDictionary.ThemeDictionaries>
        </ResourceDictionary>
    </CheckBox.Resources>
</CheckBox>
<CheckBox Content="Normal CheckBox" Margin="5"/>

Dies würde sich nur auf das eine „spezielle Kontrollkästchen“ auf der Seite auswirken, auf der dieses Steuerelement vorhanden ist.

Benutzerdefinierte Steuerelemente

Wenn Sie Ihre eigenen benutzerdefinierten Steuerelemente erstellen, die möglicherweise visuell und/oder funktionell an unsere integrierten Steuerelemente ausgerichtet sind, sollten Sie die Verwendung impliziter Formatierungs- und Lightweight-Formatierungsressourcen in Betracht ziehen, um Ihre benutzerdefinierten Inhalte zu definieren. Sie können die Ressourcen entweder direkt verwenden oder einen neuen Alias für die Ressource erstellen.

Direkte Nutzung von Steuerungsressourcen

Wenn Sie beispielsweise ein Steuerelement erstellen, das wie eine Schaltfläche aussieht, kann Ihr Steuerelement direkt auf die Schaltflächenressourcen zugreifen, so:

<Style TargetType="local:MyCustomControl">
  <Setter Property="Background" Value="{ThemeResource ButtonBackground}" />
  <Setter Property="BorderBrush" Value="{ThemeResource ButtonBorderBrush}" />
</Style>

Aliasing von Steuerelementressourcen für neue Namen

Wenn Sie alternativ Ihre eigenen Ressourcen erstellen möchten, sollten Sie diese benutzerdefinierten Namen unseren standardmäßigen Lightweight-Formatvorlagenressourcen zuweisen.

Die Formatvorlage des benutzerdefinierten Steuerelements kann beispielsweise spezielle Ressourcendefinitionen aufweisen:

<Style TargetType="local:MyCustomControl">
  <Setter Property="Background" Value="{ThemeResource MyCustomControlBackground}" />
  <Setter Property="BorderBrush" Value="{ThemeResource MyCustomControlBorderBrush}"/>
</Style>

In Ihrem Ressourcenwörterbuch oder Ihrer Hauptdefinition würden Sie die Lightweight-Formatvorlagenressourcen mit Ihren benutzerdefinierten Ressourcen verknüpfen:

<ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Default">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>        
    <ResourceDictionary x:Key="Light">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>
    <ResourceDictionary x:Key="HighContrast">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

Es ist erforderlich, dass Sie ein ThemeDictionary verwenden, das dreimal dupliziert wird, um die drei verschiedenen Designänderungen ordnungsgemäß zu behandeln (Default, Light, HighContrast).

Vorsicht

Wenn Sie einer neuen Alias-Ressource eine Lightweight-Formatvorlagenressource zuweisen und die Lightweight-Formatvorlagenressource außerdem neu definieren, wird Ihre Anpassung möglicherweise nicht angewendet, wenn die Ressourcensuche nicht in der richtigen Reihenfolge erfolgt. Wenn Sie beispielsweise ButtonBackground an einer Stelle überschreiben, die gesucht wird, bevor MyCustomControlBackground gefunden wird, würde das Überschreiben verfehlt werden.

Vermeiden von Umformatierungs-Steuerelementen

Die beste Möglichkeit, mit unseren neuesten visuellen Stilen auf dem neuesten Stand zu bleiben, besteht darin, benutzerdefinierte Stile und Vorlagen (auch als erneute Vorlagen bezeichnet) zu vermeiden. Stile sind immer noch eine bequeme Möglichkeit, eine Reihe von Werten konsistent über Steuerelemente in Ihrer App anzuwenden. Stellen Sie dabei sicher, dass diese auf unseren neuesten Formatvorlagen basieren.

Für ein WinUI-Steuerelement im Namespace Microsoft.UI.Xaml.Controls, das einen benannten Standardstil bereitstellt, legen Sie BasedOn="{StaticResource Default<ControlName>Style}" fest, wobei <ControlName> der Name des Steuerelements ist. Dadurch wird die Standardvorlage und die visuellen Zustände des Steuerelements beibehalten. Beispiel:

<Style TargetType="TextBox" BasedOn="{StaticResource DefaultTextBoxStyle}">
    <Setter Property="Foreground" Value="Blue"/>
</Style>

Abgeleitete Steuerelemente

Wenn Sie ein benutzerdefiniertes Steuerelement von einem vorhandenen XAML-Steuerelement ableiten, erhält es standardmäßig möglicherweise nicht immer die WinUI-Formatvorlagen. So wenden Sie die WinUI-Formatvorlagen an:

  • Erstellen Sie eine neue Formatvorlage, deren TargetType auf Ihr benutzerdefiniertes Steuerelement festgelegt ist.
  • Basieren Sie die Formatvorlage auf der Standardformatvorlage des Steuerelements, von dem Sie abgeleitet haben.

Ein häufiges Szenario hierfür ist das Ableiten eines neuen Steuerelements von ContentDialog. In diesem Beispiel wird gezeigt, wie Sie eine neue Formatvorlage erstellen, die DefaultContentDialogStyle auf Ihr benutzerdefiniertes Dialogfeld festlegt.

<ContentDialog
    x:Class="ExampleApp.SignInContentDialog"
    ... >

    <ContentDialog.Resources>
        <Style TargetType="local:SignInContentDialog" BasedOn="{StaticResource DefaultContentDialogStyle}"/>
        ...
    </ContentDialog.Resources> 
    <!-- CONTENT -->
</ContentDialog>        

Die template-Eigenschaft

Für die Template-Eigenschaft eines Control-Elements kann ein Stilsetter verwendet werden. Dieser erstellt letztendlich den größten Teil eines typischen XAML-Stils und der XAML-Ressourcen einer App. Dies wird in den Steuerelementvorlagen ausführlicher erläutert.