Styles XAML

Vous pouvez personnaliser l’apparence de vos applications de plusieurs façons à l’aide de l’infrastructure XAML. Les styles vous permettent de définir des propriétés de contrôle et de réutiliser ces paramètres pour une apparence cohérente entre plusieurs contrôles.

Principes de base du style

Utilisez des styles pour extraire les paramètres de propriété visuelle dans des ressources réutilisables. Voici un exemple montrant 3 boutons avec un style qui définit les propriétés BorderBrush , BorderThickness et Foreground . En appliquant un style, vous pouvez rendre les contrôles identiques sans avoir à définir ces propriétés sur chaque contrôle séparément.

Capture d’écran de trois boutons stylisés placés côte à côte.

Vous pouvez définir un style inline dans le code XAML pour un contrôle ou en tant que ressource réutilisable. Définissez les ressources dans le fichier XAML d’une page individuelle, dans le fichier App.xaml ou dans un fichier XAML de dictionnaire de ressources distinct. Un fichier XAML de dictionnaire de ressources peut être partagé entre les applications, et plusieurs dictionnaires de ressources peuvent être fusionnés dans une seule application. L’emplacement où la ressource est définie détermine l’étendue dans laquelle elle peut être utilisée. Les ressources au niveau de la page sont disponibles uniquement dans la page où elles sont définies. Si les ressources avec la même clé sont définies dans App.xaml et dans une page, la ressource de la page remplace la ressource dans App.xaml. Si une ressource est définie dans un fichier de dictionnaire de ressources distinct, son étendue est déterminée par l’emplacement où le dictionnaire de ressources est référencé.

Dans la définition d'un Style, vous avez besoin d’un attribut TargetType et d’une collection avec un ou plusieurs éléments Setter. L’attribut TargetType est une chaîne qui spécifie un type FrameworkElement auquel appliquer le style. La valeur TargetType doit spécifier un type dérivé de FrameworkElement défini par Windows Runtime ou un type personnalisé disponible dans un assembly référencé. Si vous essayez d’appliquer un style à un contrôle et que le type du contrôle ne correspond pas à l’attribut TargetType du style que vous essayez d’appliquer, une exception se produit.

Chaque élément Setter nécessite une Property et une Value. Ces paramètres de propriété indiquent la propriété de contrôle à laquelle le paramètre s’applique et la valeur à définir pour cette propriété. Vous pouvez définir Setter.Value avec une syntaxe d’attribut ou d’élément de propriété. Le code XAML montre ici le style appliqué aux boutons affichés précédemment. Dans ce code XAML, les deux premiers éléments Setter utilisent la syntaxe d’attribut, mais le dernier Setter, pour la propriété BorderBrush , utilise la syntaxe de l’élément de propriété. L’exemple n’utilise pas l’attribut x :Key attribut. Le style est donc implicitement appliqué aux boutons. L’application de styles implicitement ou explicitement est expliquée dans la section suivante.

<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>

Appliquer un style implicite ou explicite

Si vous définissez un style en tant que ressource, il existe deux façons de l’appliquer à vos contrôles :

  • Implicitement, en spécifiant uniquement un TargetType pour Style.
  • Explicitement, en spécifiant un TargetType et un attribut x:Key pour le Style, puis en définissant la propriété Style du contrôle cible avec une référence d'extension de balisage {StaticResource} qui utilise la clé explicite.

Si un style contient l’attribut x:Key, vous ne pouvez l’appliquer à un contrôle qu’en définissant la propriété Style du contrôle sur le style associé à la clé. En revanche, un style sans attribut x:Key est automatiquement appliqué à tous les contrôles de son type cible qui n’ont pas de paramètre de style explicite.

Voici deux boutons qui illustrent des styles implicites et explicites.

boutons de style implicite et explicite.

Dans cet exemple, le premier style a un attribut x :Key et son type cible est Button. La propriété Style du premier bouton est définie sur cette touche. Ce style est donc appliqué explicitement. Le deuxième style est appliqué implicitement au deuxième bouton, car son type cible est Button et le style n’a pas d’attribut x :Key.

<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>

Utiliser des styles dérivés

Pour faciliter la maintenance et la réutilisation des styles, vous pouvez créer des styles qui héritent d’autres styles. Utilisez la propriété BasedOn pour créer des styles hérités. Les styles qui héritent d’autres styles doivent cibler le même type de contrôle ou un contrôle qui dérive du type ciblé par le style de base. Par exemple, si un style de base cible ContentControl, les styles basés sur ce style peuvent cibler ContentControl ou des types dérivés de ContentControl , tels que Button et ScrollViewer. Si une valeur n’est pas définie dans le style basé, elle est héritée du style de base. Pour modifier une valeur du style de base, le style basé sur la base remplace cette valeur. L’exemple suivant montre un Bouton et un CheckBox avec des styles qui héritent du même style de base.

boutons utilisant des styles dérivés.

Le style de base cible ContentControl et définit les propriétés Height et Width . Les styles basés sur ce style ciblent CheckBox et Button, lesquels dérivent de ContentControl. Les styles dérivés définissent des couleurs différentes pour les propriétés BorderBrush et Foreground. (Vous ne placez généralement pas de bordure autour d’un CheckBox. Nous le faisons ici pour montrer les effets du style.)

<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>

Styles légers

Le remplacement des pinceaux système est généralement effectué au niveau de l’application ou de la page. Dans les deux cas, le remplacement de couleur affecte tous les contrôles qui référencent ce pinceau , et dans XAML, de nombreux contrôles peuvent référencer le même pinceau système.

Capture d’écran de deux boutons : l’un au repos et l’autre avec un style léger.

<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>

Pour les états tels que PointerOver (la souris est pointée sur le bouton), PointerPressé (le bouton a été invité) ou Désactivé (le bouton n'est pas interactif). les terminaisons suivantes sont ajoutées aux noms de style léger d’origine : ButtonBackgroundPointerOver, ButtonForegroundPressed, ButtonBorderBrushDisabled, etc. La modification de ces pinceaux vous permet également de veiller à ce que les couleurs de vos contrôles soient en accord avec le thème de votre application.

Ces remplacements de pinceau au niveau App.Resources modifie l'ensemble des boutons de l’application, et non pas une seule page.

Application de styles par contrôle

Dans d’autres cas, la modification d’un seul contrôle sur une seule page pour ressembler à une certaine façon, sans modifier d’autres versions de ce contrôle, est souhaitée :

Capture d’écran de trois boutons stylisés empilés.

<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"/>

Cela n’affecterait qu’un « CheckBox spécial » sur la page où ce contrôle existait.

Contrôles personnalisés

Lorsque vous créez vos propres contrôles personnalisés qui peuvent être visuellement et/ou fonctionnellement alignés avec nos contrôles intégrés, envisagez d’utiliser des ressources de style implicites et de style léger pour définir votre contenu personnalisé. Vous pouvez utiliser les ressources directement ou créer un alias pour la ressource.

Utilisation directe des ressources de contrôle

Par exemple, si vous écrivez un contrôle qui ressemble à un bouton, vous pouvez faire référence aux ressources du bouton directement, comme suit :

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

Attribution de nouveaux alias à des ressources de contrôle

Sinon, si vous préférez créer vos propres ressources, vous devez alias ces noms personnalisés à nos ressources de style légères par défaut.

Par exemple, le style de votre contrôle personnalisé peut avoir des définitions de ressources spéciales :

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

Dans votre dictionnaire de ressources ou définition principale, vous devez raccorder les ressources de style légères à vos ressources personnalisées :

<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>

Il est nécessaire d’utiliser un ThemeDictionary qui est dupliqué trois fois pour gérer correctement les trois modifications de thème différentes (Default, Light, HighContrast).

Avertissement

Si vous affectez une ressource de style léger à un nouvel alias et redéfinissez également la ressource de style Léger, votre personnalisation peut ne pas être appliquée si la recherche de ressources n’est pas dans l’ordre correct. Par exemple, si vous remplacez ButtonBackground à un emplacement qui est recherché avant que MyCustomControlBackground ne soit trouvé, le remplacement ne se fait pas.

Éviter les contrôles de changement de style

La meilleure façon de rester à jour avec nos derniers styles visuels consiste à éviter les styles et modèles personnalisés (également appelés re-templating). Les styles sont toujours un moyen pratique d’appliquer un ensemble de valeurs de manière cohérente entre les contrôles de votre application. Assurez-vous de vous baser sur nos styles les plus récents lorsque vous effectuez cette opération.

Pour les contrôles système qui utilisent des styles WinUI (Microsoft.UI.Xaml.Controls espace de noms), définissez BasedOn="{StaticResource Default<ControlName>Style}", où <ControlName> est le nom du contrôle. Par exemple:

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

Pour les contrôles WinUI (Microsoft.UI.Xaml.Controlsespace de noms), le style par défaut est défini dans les métadonnées. Par conséquent, omettez.BasedOn

Contrôles dérivés

Si vous dérivez un contrôle personnalisé d’un contrôle XAML existant, il peut ne pas toujours obtenir les styles WinUI par défaut. Pour appliquer les styles WinUI :

  • Créez un nouveau Style dont le TargetType est défini sur votre contrôle personnalisé.
  • Basez le style sur le style par défaut du contrôle à partir duquel vous avez dérivé.

Un scénario courant pour cela consiste à faire dériver un nouveau contrôle de ContentDialog. Cet exemple montre comment créer un nouveau style qui applique DefaultContentDialogStyle à votre boîte de dialogue personnalisée.

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

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

Propriété du modèle

Un setter de style peut être utilisé pour la propriété Template d’un contrôle. En fait, cela constitue la majorité d’un style XAML classique et des ressources XAML d’une application. Ceci est abordé plus en détail dans la rubrique modèles de contrôle.