Partage via


Styles XAML

Vous pouvez personnaliser l'apparence de vos applications de plusieurs manières à l'aide du framework XAML. Les styles vous permettent de définir les propriétés des contrôles et de réutiliser ces paramètres pour une apparence cohérente sur plusieurs contrôles.

WinUI et styles

À compter de WinUI 2.2, nous avons utilisé WinUI pour fournir de nouvelles mises à jour des styles visuels de nos composants d’interface utilisateur. Si vous remarquez que votre interface utilisateur n’est pas mise à jour vers les derniers styles, assurez-vous d'effectuer une mise à jour vers le dernier package NuGet pour WinUI.

À compter de WinUI 2.6, nous fournissons de nouveaux styles pour la plupart des contrôles, ainsi qu'un nouveau système de contrôle de versions qui vous permet, en cas de besoin, de revenir aux styles de contrôle précédents. Nous vous encourageons à utiliser les nouveaux styles, car ils s'alignent mieux sur la direction de conception de Windows. Cependant, si votre scénario ne peut pas prendre en charge les nouveaux styles, les versions précédentes sont toujours disponibles.

Pour modifier la version des styles, définissez la propriété ControlsResourcesVersion sur le XamlControlsResources que vous incluez dans votre Application.Resources lorsque vous utilisez WinUI version 2. ControlsResourcesVersion utilise par défaut la valeur enum Version2.

Si cette valeur est définie sur Version1, XamlControlsResources charge les versions de styles précédentes au lieu des nouveaux styles utilisés par la dernière version de WinUI. La modification de cette propriété en cours d’exécution n’est pas prise en charge et la fonctionnalité de rechargement à chaud de VisualStudio ne fonctionnera pas. Vous verrez la modification des styles de contrôle une fois que votre application aura été régénérée.

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

Principes de base des styles

Utilisez des styles pour extraire des paramètres de propriété visuelle dans des ressources réutilisables. Voici un exemple montrant 3 boutons dont le style définit les propriétés BorderBrush, BorderThickness et Foreground. En appliquant un style, vous pouvez faire en sorte que les contrôles soient identiques sans avoir à définir ces propriétés sur chacun d'eux séparément.

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

Vous pouvez définir un style inclus dans 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 plusieurs applications, et il est possible de fusionner plusieurs dictionnaires de ressources dans une même application. L’endroit où la ressource est définie détermine la portée de son champ d'application. Les ressources au niveau de la page ne sont disponibles que dans la page où elles sont définies. Si des ressources ayant la même clé sont définies dans App.xaml et dans une page, la ressource de la page prévaut sur celle associée à 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 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 le 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 dont le type ne correspond pas à l’attribut TargetType du style que vous essayez d’appliquer, une exception se produit.

Chaque élément Setter nécessite une Propriété et une Valeur. Ces paramètres de propriété indiquent la propriété de contrôle à laquelle le paramètre s’applique, ainsi que 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 ci-dessous montre le style appliqué aux boutons précédents. 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’exemple n’utilise pas l’attribut x:Key attribute. Le style est donc implicitement appliqué aux boutons. L’application implicite ou explicite de styles 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 comme une ressource, il existe deux façons de l’appliquer à vos contrôles :

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 les styles implicite et explicite.

boutons de style 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 second style est appliqué implicitement au deuxième bouton, car son type cible est Button et aucun attribut x:Key ne lui est associé.

<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 des styles et optimiser leur réutilisation, vous pouvez créer des styles hérités d’autres styles. Utilisez la propriété BasedOn pour créer des styles hérités. Les styles hérités 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 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 une valeur n’est pas définie dans le style dérivé, elle est héritée du style de référence. Pour modifier une valeur héritée du style de référence, remplacez-la dans le style dérivé. 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 utilisant des styles dérivés.

Le style de référence cible ContentControl et définit les propriétés Height et Width. Les styles basés sur ce style ciblent les types CheckBox et Button dérivés de ContentControl. Les styles dérivés définissent des couleurs différentes pour les propriétés BorderBrush et Foreground. (En général, on ne place pas de bordure autour d’une CheckBox. Nous l'avons fait 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>

Outils pour faciliter l'utilisation des styles

Un moyen rapide d’appliquer des styles à vos contrôles consiste à cliquer avec le bouton droit sur un contrôle dans l’aire de conception XAML de Microsoft Visual Studio, puis à sélectionner Edit Style ou Edit Template (selon le contrôle sur lequel vous cliquez avec le bouton droit). Vous pouvez ensuite appliquer un style existant en sélectionnant Apply Resource ou définir un nouveau style en sélectionnant Create Empty. Si vous créez un nouveau style, vous avez la possibilité de le définir dans la page, dans le fichier App.xaml ou dans un dictionnaire de ressources distinct.

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, 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 tels que PointerOver (la souris pointe vers le bouton), PointerPressed (le bouton a été appelé) ou Disabled (le bouton n’est pas cliquable), 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, l'objectif est de modifier un seul contrôle sur une page pour lui donner une certaine apparence, sans modifier 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 que la « Special CheckBox » de la page où ce contrôle existe.

Contrôles personnalisés

Lorsque vous créez des contrôles personnalisés qui peuvent être visuellement et/ou fonctionnellement alignés sur nos contrôles intégrés, pensez à utiliser des ressources de style implicite et de style léger pour définir votre contenu personnalisé. Vous pouvez soit utiliser les ressources directement, soit créer un nouvel alias.

Utilisation directe de 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 se réfère directement aux ressources d'un bouton 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

Si vous préférez créer vos propres ressources, vous devez attribuer des alias personnalisés à nos ressources de style léger par défaut.

Par exemple, le style personnalisé de votre contrôle peut avoir des définitions de ressource 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 principale, 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>

Vous devez utiliser un ThemeDictionary qui est dupliqué trois fois pour traiter correctement les trois changements de thème (Default, Light, HighContrast).

Attention

Si vous allouez une ressource de style léger à un nouvel alias, et que vous redéfinissez également la ressource de style léger, il peut arriver que votre personnalisation ne s'applique pas si la recherche des ressources ne s'effectue pas dans le bon ordre. 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

WinUI 2.2 ou ses versions ultérieures contiennent 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 la personnalisation des styles et modèles (ou « re-templating »). Les styles restent un moyen pratique d’appliquer un ensemble de valeurs de manière uniforme à tous les contrôles de votre application. Lorsque vous le faites, assurez-vous de vous baser sur nos derniers styles.

Pour les contrôles système qui utilisent des styles WinUI (espace de noms Windows.UI.Xaml.Controls), 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 (espace de noms Microsoft.UI.Xaml.Controls), 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 faites dériver un contrôle personnalisé 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 nouveau Style dont le TargetType est défini sur votre contrôle personnalisé.
  • Basez le Style de votre contrôle personnalisé sur le style par défaut du contrôle dont il dérive.

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>        

La propriété Template

Un Style Setter peut être utilisé pour la propriété Template d’un Control, ce qui correspond d'ailleurs à la majorité des styles XAML classiques et des ressources XAML d’une application. Ce sujet est abordé plus en détail à la rubrique Modèles de contrôle.