Styles XAML

Vous pouvez personnaliser l’apparence de vos applications de nombreuses manières à l’aide de l’infrastructure XAML. Les styles permettent de définir les propriétés des contrôles et de réutiliser ces paramètres pour uniformiser l’apparence de plusieurs contrôles.

WinUI et styles

À compter de WinUI 2.2, nous avons utilisé la bibliothèque d’interface utilisateur Windows (WinUI) pour fournir de nouvelles mises à jour de style visuel sur l’ensemble de nos composants d’interface utilisateur. Si vous remarquez que votre interface utilisateur ne se met pas à jour vers les derniers styles, veillez à effectuer une mise à jour vers le dernier package NuGet WinUI.

À compter de WinUI 2.6, nous fournissons de nouveaux styles pour la plupart des contrôles et un nouveau système de contrôle de version qui vous permet de revenir aux styles de contrôle précédents si nécessaire. Nous vous encourageons à utiliser les nouveaux styles, car ils correspondent mieux au sens de conception de Windows. Toutefois, si votre scénario ne peut pas prendre en charge les nouveaux styles, les versions précédentes sont toujours disponibles.

Vous pouvez modifier la version du style en définissant la ControlsResourcesVersion propriété sur le XamlControlsResources que vous incluez dans votre Application.Resources lorsque vous utilisez WinUI version 2. ControlsResourcesVersion la valeur Version2par défaut de l’énumération .

La définition de Version1 cette valeur sur entraîne XamlControlsResources le chargement des versions de style précédentes au lieu des nouveaux styles utilisés par la dernière version de WinUI. La modification de cette propriété au moment de l’exécution n’est pas prise en charge et la fonctionnalité de rechargement à chaud de VisualStudio ne fonctionne pas . Toutefois, après avoir regénéré votre application, vous verrez les styles de contrôle changer.

<Application.Resources>
    <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" 
                           ControlsResourcesVersion="Version1"/>
</Application.Resources>

Bases des styles

Les styles permettent d’extraire des paramètres de propriété visuels afin de disposer de ressources réutilisables. Voici un exemple représentant 3 boutons avec un style définissant les propriétés BorderBrush, BorderThickness et Foreground. Lorsque vous appliquez un style, vous pouvez faire en sorte que les contrôles aient la même apparence sans définir ces propriétés pour chaque contrôle individuellement.

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

Vous pouvez définir un style inline en langage XAML pour un contrôle ou sous la forme de ressource réutilisable. Vous définissez les ressources dans le fichier XAML d’une page individuelle, dans le fichier App.xaml ou dans le fichier XAML d’un dictionnaire de ressources distinct. Le fichier XAML d’un dictionnaire de ressources peut être partagé entre plusieurs applications et plusieurs dictionnaires de ressources peuvent être fusionnés dans une seule application. L’endroit où la ressource est définie détermine l’étendue (champ d’application) de son utilisation. Les ressources au niveau page sont uniquement disponibles dans la page où elles sont définies. Si des ressources sont définies avec la même clé à la fois dans App.xaml et dans une page, la ressource de la page remplace la ressource de App.xaml. Si une ressource est définie dans un fichier de dictionnaire de ressources distinct, son étendue est déterminée par l’endroit où le dictionnaire de ressources est référencé.

Dans la définition de Style, vous avez besoin d’un attribut TargetType et d’une collection d’un ou de plusieurs éléments Setter. L’attribut TargetType est une chaîne qui spécifie le type FrameworkElement auquel appliquer le style. La valeur TargetType doit spécifier un type dérivé de FrameworkElement qui est 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 de ce 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 un élément Property et Value. Ces paramètres de propriété indiquent quelle est la propriété de contrôle à laquelle ce paramètre s’applique, ainsi que la valeur à définir pour cette propriété. Vous pouvez définir la valeur Setter.Value avec une syntaxe d’attribut ou une syntaxe d’élément de propriété. Le code XAML ci-dessous montre le style appliqué aux boutons illustrés précédemment. Dans ce code XAML, les deux premiers éléments Setter utilisent une syntaxe d’attribut, tandis que le dernier élément Setter, relatif à la propriété BorderBrush, utilise une syntaxe d’élément de propriété. L’attribut x:Key n’étant pas utilisé, le style est appliqué implicitement aux boutons. La section suivante explique la notion d’application implicite et explicite de styles.

<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 de manière implicite ou explicite

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

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é à chaque contrôle de son type cible qui, sinon, n’a pas de paramètre de style explicite.

Voici deux boutons illustrant les styles implicite et explicite.

Boutons aux styles implicite et explicite

Dans cet exemple, l’attribut x:Key est associé au premier style et le type cible de ce dernier est Button. La propriété Style du premier bouton est définie sur cette clé : le style est donc appliqué explicitement. Le type cible du deuxième style est Button et aucun attribut x:Key n’est associé à ce dernier : le style est donc appliqué implicitement au deuxième bouton.

<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 basés sur d’autres styles

Pour faciliter la gestion des styles et optimiser leur réutilisation, vous pouvez créer des styles héritant d’autres styles. Pour créer des styles hérités, vous devez utiliser la propriété BasedOn. Les styles héritant d’autres styles doivent cibler le même type de contrôle ou un contrôle dérivé du type ciblé par le style de référence. Par exemple, si le contrôle cible du style de référence est ContentControl, les styles basés sur ce style peuvent cibler également ContentControl ou des types dérivés de ContentControl , tels que Button et ScrollViewer. Si vous ne définissez aucune valeur dans le style qui hérite, celle du style de référence est utilisée. Pour modifier une valeur issue du style de référence, le style qui hérite écrase cette valeur. L’exemple suivant présente un type Button et un type CheckBox avec des styles basés sur le même style de référence.

Boutons stylés à l’aide de styles basés sur d’autres styles

Le type cible du style de référence est ContentControl, et les propriétés Height et Width sont définies pour ce style. Les styles basés sur ce style ciblent les types CheckBox et Button dérivés de ContentControl. Des couleurs différentes sont définies pour les propriétés BorderBrush et Foreground de ces styles. (En règle générale, vous ne placez pas de bordure autour d’un contrôle 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>

Utilisation de styles en toute simplicité à l’aide d’outils

Pour appliquer rapidement des styles à vos contrôles, cliquez avec le bouton droit sur un contrôle dans l’aire de conception XAML de Microsoft Visual Studio et sélectionnez Modifier le style ou Modifier le modèle (selon le contrôle concerné). Vous pouvez ensuite appliquer un style existant en sélectionnant Appliquer la ressource ou en définir un nouveau en sélectionnant Créer vide. Si vous créez un style vide, vous avez l’option de le définir dans la page, dans le fichier App.xaml ou dans un dictionnaire de ressources distinct.

Création d’un style léger

Le remplacement des pinceaux système est généralement effectué au niveau de l’application ou de la page. Dans les deux cas, la substitution de la couleur s’appliquera à tous les contrôles qui font référence à ce pinceau (dans du code 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 du type PointerOver (souris déplacée sur le bouton), PointerPressed (activation du bouton), ou Disabled (impossible d’interagir avec le bouton). Ces terminaisons sont ajoutées aux noms de style Lightweight d’origine : ButtonBackgroundPointerOver, ButtonForegroundPressed, ButtonBorderBrushDisabled, etc. La modification de ces pinceaux permet également de s’assurer que vos contrôles sont colorés de manière cohérente avec le thème de votre application.

Le fait de placer ces remplacements de pinceau au niveau App.Resources a pour effet d’affecter tous les boutons de l’ensemble de votre application, et non une seule page.

Création d’un style par contrôle

Dans d’autres cas, il peut être souhaitable de modifier un seul contrôle sur une même page afin de lui affecter un style donné, sans altérer les autres versions de ce contrôle :

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’une seule « CheckBox spéciale » 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 implicite 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 en sorte que votre contrôle référence les ressources du bouton directement, comme suit :

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

Alias de ressources de contrôle vers de nouveaux noms

Sinon, si vous préférez créer vos propres ressources, vous devez ajouter ces noms personnalisés à nos ressources de style léger 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 votre définition de main, vous devez raccorder les ressources de style Léger à 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 que vous utilisiez un ThemeDictionary qui est dupliqué trois fois afin de gérer correctement les trois modifications de thème différentes (Default, Light, HighContrast).

Attention

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

Éviter le restyling des contrôles

La bibliothèque d’interface utilisateur Windows 2.2 ou ultérieure inclut de nouveaux styles et modèles pour les contrôles WinUI et système.

La meilleure façon de rester à jour avec nos derniers styles visuels consiste à utiliser le dernier package WinUI 2 et à éviter les styles et modèles personnalisés (également appelés re-création de modèles). 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. Dans ce cas, assurez-vous d’être basé sur nos derniers styles.

Pour les contrôles système qui utilisent des styles WinUI (Windows.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 2 (Microsoft.UI.Xaml.Controls espace de noms), le style par défaut est défini dans les métadonnées, omettez BasedOndonc .

Contrôles dérivés

Si vous dérivez un contrôle personnalisé à partir d’un contrôle XAML existant, il n’obtient pas les styles WinUI 2 par défaut. Pour appliquer les styles WinUI 2 :

  • Créez un style avec son TargetType défini sur votre contrôle personnalisé.
  • Basez le style sur le style par défaut du contrôle dont vous êtes dérivé.

L’un des scénarios courants consiste à dériver un nouveau contrôle à partir de ContentDialog. Cet exemple montre comment créer un style qui s’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é Template

Il est possible d’utiliser un setter de style pour la propriété Template d’un élément Control. En réalité, cela constitue la majorité d’un style XAML classique et des ressources XAML d’une application . Ce sujet est abordé de manière plus détaillée dans la rubrique Modèles de contrôles.