Appliquer un style aux applications à l’aide de XAML

Les applications .NET Multiplateforme App UI (.NET MAUI) contiennent souvent plusieurs contrôles qui ont une apparence identique. Par exemple, une application peut avoir plusieurs Label instances qui ont les mêmes options de police et les mêmes options de disposition :

<Label Text="These labels"
       HorizontalOptions="Center"
       VerticalOptions="Center"
       FontSize="18" />
<Label Text="are not"
       HorizontalOptions="Center"
       VerticalOptions="Center"
       FontSize="18" />
<Label Text="using styles"
       HorizontalOptions="Center"
       VerticalOptions="Center"
       FontSize="18" />

Dans cet exemple, chaque Label objet a des valeurs de propriété identiques pour contrôler l’apparence du texte affiché par le Label. Toutefois, la définition de l’apparence de chaque contrôle individuel peut être répétitive et sujette aux erreurs. Au lieu de cela, un style peut être créé qui définit l’apparence, puis appliqué aux contrôles requis.

Présentation des styles

Une application peut être mise en forme à l’aide de la Style classe pour regrouper une collection de valeurs de propriété dans un objet qui peut ensuite être appliqué à plusieurs éléments visuels. Cela permet de réduire les marques répétitives et permet à une apparence des applications d’être plus facilement modifiée.

Bien que les styles soient conçus principalement pour les applications XAML, ils peuvent également être créés en C# :

  • StyleLes objets créés en XAML sont généralement définis dans une collection affectée à la Resources collection d’un contrôle, d’une ResourceDictionary page ou à la Resources collection de l’application.
  • Style Les objets créés en C# sont généralement définis dans la classe de la page ou dans une classe accessible globalement.

Le fait de choisir où définir Style impacte l’emplacement où il peut être utilisé :

  • Style les instances définies au niveau du contrôle ne peuvent être appliquées qu’au contrôle et à ses enfants.
  • Style les instances définies au niveau de la page ne peuvent être appliquées qu’à la page et à ses enfants.
  • Style Les instances définies au niveau de l’application peuvent être appliquées tout au long de l’application.

Chaque Style objet contient une collection d’un ou plusieurs Setter objets, chacun Setter ayant un Property et un Value. Property est le nom de la propriété pouvant être liée de l’élément auquel le style est appliqué, et Value est la valeur qui est appliquée à la propriété.

Chaque Style objet peut être explicite ou implicite :

  • Un objet expliciteStyle est défini en spécifiant une TargetType valeur et en x:Key définissant la propriété de Style l’élément cible sur la x:Key référence. Pour plus d’informations, consultez Styles explicites.
  • Un objet impliciteStyle est défini en spécifiant uniquement un TargetType. L’objet Style sera ensuite appliqué automatiquement à tous les éléments de ce type. Toutefois, les sous-classes de l’application TargetType n’ont pas automatiquement été Style appliquées. Pour plus d’informations, consultez Styles implicites.

Durant la création de Style, la propriété TargetType est toujours obligatoire. L’exemple suivant montre un style explicite :

<Style x:Key="labelStyle" TargetType="Label">
    <Setter Property="HorizontalOptions" Value="Center" />
    <Setter Property="VerticalOptions" Value="Center" />
    <Setter Property="FontSize" Value="18" />
</Style>

Pour appliquer un Style, l’objet cible doit être un VisualElement qui correspond à la valeur de propriété TargetType du Style:

<Label Text="Demonstrating an explicit style" Style="{StaticResource labelStyle}" />

Les styles inférieurs dans la hiérarchie d’affichage sont prioritaires sur ceux définis plus haut. Par exemple, la définition d’un Style paramètre RedLabel.TextColor défini au niveau de l’application sera remplacée par un style de niveau page défini Label.TextColorGreensur . De même, un style au niveau de la page sera remplacé par un style au niveau du contrôle. En outre, si Label.TextColor elle est définie directement sur une propriété de contrôle, elle est prioritaire sur tous les styles.

Les styles ne répondent pas aux modifications de propriété et restent inchangés pendant la durée d’une application. Toutefois, les applications peuvent répondre aux modifications de style dynamiquement au moment de l’exécution à l’aide de ressources dynamiques. Pour plus d’informations, consultez Styles dynamiques.

Styles explicites

Pour créer une Style page au niveau de la page, une ResourceDictionary doit être ajoutée à la page, puis une ou plusieurs Style déclarations peuvent être incluses dans le ResourceDictionary. A Style est rendu explicite en donnant à sa déclaration un x:Key attribut, qui lui donne une clé descriptive dans le ResourceDictionary. Les styles explicites doivent ensuite être appliqués à des éléments visuels spécifiques en définissant leurs Style propriétés.

L’exemple suivant montre des styles explicites dans les objets d’une ResourceDictionarypage et appliqués aux objets de Label la page :

<ContentPage ...>
    <ContentPage.Resources>
        <Style x:Key="labelRedStyle"
               TargetType="Label">
            <Setter Property="HorizontalOptions" Value="Center" />
            <Setter Property="VerticalOptions" Value="Center" />
            <Setter Property="FontSize" Value="18" />
            <Setter Property="TextColor" Value="Red" />
        </Style>
        <Style x:Key="labelGreenStyle"
               TargetType="Label">
            <Setter Property="HorizontalOptions" Value="Center" />
            <Setter Property="VerticalOptions" Value="Center" />
            <Setter Property="FontSize" Value="18" />
            <Setter Property="TextColor" Value="Green" />
        </Style>
        <Style x:Key="labelBlueStyle"
               TargetType="Label">
            <Setter Property="HorizontalOptions" Value="Center" />
            <Setter Property="VerticalOptions" Value="Center" />
            <Setter Property="FontSize" Value="18" />
            <Setter Property="TextColor" Value="Blue" />
        </Style>
    </ContentPage.Resources>
    <StackLayout>
        <Label Text="These labels"
               Style="{StaticResource labelRedStyle}" />
        <Label Text="are demonstrating"
               Style="{StaticResource labelGreenStyle}" />
        <Label Text="explicit styles,"
               Style="{StaticResource labelBlueStyle}" />
        <Label Text="and an explicit style override"
               Style="{StaticResource labelBlueStyle}"
               TextColor="Teal" />
    </StackLayout>
</ContentPage>

Dans cet exemple, les ResourceDictionary trois styles définis explicitement sur les objets de Label la page sont définis. Chacun Style est utilisé pour afficher du texte dans une couleur différente, tout en définissant également la taille de police et les options de disposition horizontale et verticale. Chacun d’eux Style est appliqué à un autre Label en définissant ses Style propriétés à l’aide de l’extension de StaticResource balisage. En outre, alors que le final Label a un Style ensemble sur celui-ci, il remplace également la TextColor propriété par une autre Color valeur.

Styles implicites

Pour créer une Style page au niveau de la page, une ResourceDictionary doit être ajoutée à la page, puis une ou plusieurs Style déclarations peuvent être incluses dans le ResourceDictionary. Un Style élément est impliciteen ne spécifiant pas d’attributx:Key. Le style sera ensuite appliqué aux éléments visuels d’étendue qui correspondent TargetType exactement, mais pas aux éléments dérivés de la TargetType valeur.

L’exemple de code suivant montre un style implicite dans les objets d’une ResourceDictionarypage et appliqué aux objets de Entry la page :

<ContentPage ...>
    <ContentPage.Resources>
        <Style TargetType="Entry">
            <Setter Property="HorizontalOptions" Value="Fill" />
            <Setter Property="VerticalOptions" Value="Center" />
            <Setter Property="BackgroundColor" Value="Yellow" />
            <Setter Property="FontAttributes" Value="Italic" />
            <Setter Property="TextColor" Value="Blue" />
        </Style>
    </ContentPage.Resources>
    <StackLayout>
        <Entry Text="These entries" />
        <Entry Text="are demonstrating" />
        <Entry Text="implicit styles," />
        <Entry Text="and an implicit style override"
               BackgroundColor="Lime"
               TextColor="Red" />
        <local:CustomEntry Text="Subclassed Entry is not receiving the style" />
    </StackLayout>
</ContentPage>

Dans cet exemple, le code ResourceDictionary définit un style implicite unique qui est implicitement défini sur les objets de Entry la page. Il Style est utilisé pour afficher du texte bleu sur un arrière-plan jaune, tout en définissant d’autres options d’apparence. Il Style est ajouté aux pages ResourceDictionary sans spécifier d’attribut x:Key . Par conséquent, l’objet Style est appliqué implicitement à tous les Entry objets, car ils correspondent à la TargetType propriété de l’objet Style exactement. Toutefois, l’objet Style n’est pas appliqué CustomEntry , qui est une sous-classe Entry. En outre, le quatrième Entry remplace les propriétés et TextColor les BackgroundColor propriétés du style par différentes Color valeurs.

Appliquer un style aux types dérivés

La Style.ApplyToDerivedTypes propriété permet d’appliquer un style aux contrôles dérivés du type de base référencé par la TargetType propriété. Par conséquent, la définition de cette propriété permet à true un style unique de cibler plusieurs types, à condition que les types dérivent du type de base spécifié dans la TargetType propriété.

L’exemple suivant montre un style implicite qui définit la couleur d’arrière-plan des Button instances en rouge :

<Style TargetType="Button"
       ApplyToDerivedTypes="True">
    <Setter Property="BackgroundColor"
            Value="Red" />
</Style>

Le placement de ce style au niveau ResourceDictionary de la page entraîne son application à tous les Button objets de la page, ainsi qu’aux contrôles qui dérivent de Button. Toutefois, si la ApplyToDerivedTypes propriété n’est pas définie, le style ne sera appliqué qu’aux Button objets.

Styles globaux

Les styles peuvent être définis globalement en les ajoutant au dictionnaire de ressources de l’application. Ces styles peuvent ensuite être consommés dans une application et vous aider à éviter la duplication de style entre les pages et les contrôles.

L’exemple suivant montre une Style définition au niveau de l’application :


<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:Styles"
             x:Class="Styles.App">
    <Application.Resources>        
        <Style x:Key="buttonStyle" TargetType="Button">
            <Setter Property="HorizontalOptions"
                        Value="Center" />
            <Setter Property="VerticalOptions"
                        Value="CenterAndExpand" />
            <Setter Property="BorderColor"
                        Value="Lime" />
            <Setter Property="CornerRadius"
                        Value="5" />
            <Setter Property="BorderWidth"
                        Value="5" />
            <Setter Property="WidthRequest"
                        Value="200" />
            <Setter Property="TextColor"
                        Value="Teal" />
        </Style>
    </Application.Resources>
</Application>

Dans cet exemple, le modèle ResourceDictionary définit un style explicite unique, buttonStylequi sera utilisé pour définir l’apparence des Button objets.

Remarque

Les styles globaux peuvent être explicites ou implicites.

L’exemple suivant montre une page qui consomme les buttonStyle objets de Button la page :

<ContentPage ...>
    <StackLayout>
        <Button Text="These buttons"
                Style="{StaticResource buttonStyle}" />
        <Button Text="are demonstrating"
                Style="{StaticResource buttonStyle}" />
        <Button Text="application styles"
                Style="{StaticResource buttonStyle}" />
    </StackLayout>
</ContentPage>

Héritage de style

Les styles peuvent hériter d’autres styles pour réduire la duplication et activer la réutilisation. Pour ce faire, définissez la Style.BasedOn propriété sur un objet existant Style. En XAML, cela peut être obtenu en définissant la BasedOn propriété sur une StaticResource extension de balisage qui fait référence à un fichier créé Styleprécédemment.

Les styles qui héritent d’un style de base peuvent inclure des Setter instances pour de nouvelles propriétés ou les utiliser pour remplacer les setters du style de base. En outre, les styles qui héritent d’un style de base doivent cibler le même type, ou un type qui dérive du type ciblé par le style de base. Par exemple, si un style de base cible View des objets, les styles basés sur le style de base peuvent cibler View des objets ou des types dérivés de la View classe, tels que Label des objets et Button des objets.

Un style peut hériter uniquement des styles au même niveau, ou supérieur, dans la hiérarchie d’affichage. Ce qui signifie que :

  • Un style au niveau de l’application ne peut hériter que d’autres styles au niveau de l’application.
  • Un style de niveau page peut hériter des styles au niveau de l’application et d’autres styles de niveau page.
  • Un style au niveau du contrôle peut hériter des styles au niveau de l’application, des styles de niveau page et d’autres styles de niveau contrôle.

L’exemple suivant montre l’héritage de style explicite :

<ContentPage ...>
    <ContentPage.Resources>
        <Style x:Key="baseStyle"
               TargetType="View">
            <Setter Property="HorizontalOptions" Value="Center" />
            <Setter Property="VerticalOptions" Value="Center" />
        </Style>
    </ContentPage.Resources>
    <StackLayout>
        <StackLayout.Resources>
            <Style x:Key="labelStyle"
                   TargetType="Label"
                   BasedOn="{StaticResource baseStyle}">
                <Setter Property="FontSize" Value="18" />
                <Setter Property="FontAttributes" Value="Italic" />
                <Setter Property="TextColor" Value="Teal" />
            </Style>
            <Style x:Key="buttonStyle"
                   TargetType="Button"
                   BasedOn="{StaticResource baseStyle}">
                <Setter Property="BorderColor" Value="Lime" />
                <Setter Property="CornerRadius" Value="5" />
                <Setter Property="BorderWidth" Value="5" />
                <Setter Property="WidthRequest" Value="200" />
                <Setter Property="TextColor" Value="Teal" />
            </Style>
        </StackLayout.Resources>
        <Label Text="This label uses style inheritance"
               Style="{StaticResource labelStyle}" />
        <Button Text="This button uses style inheritance"
                Style="{StaticResource buttonStyle}" />
    </StackLayout>
</ContentPage>

Dans cet exemple, les baseStyle objets cibles View et définit les propriétés et VerticalOptions les HorizontalOptions propriétés. Le baseStyle paramètre n’est pas défini directement sur les contrôles. Au lieu de cela, et buttonStyle héritez-en, labelStyle en définissant des valeurs de propriété pouvant être liées supplémentaires. Les labelStyle objets et buttonStyle les objets sont ensuite définis sur un Label et Button.

Important

Un style implicite peut être dérivé d’un style explicite, mais un style explicite ne peut pas être dérivé d’un style implicite.

Styles dynamiques

Les styles ne répondent pas aux modifications de propriété et restent inchangés pendant la durée d’une application. Par exemple, après avoir affecté un Style élément visuel, si l’un des Setter objets est modifié, supprimé ou ajouté Setter , les modifications ne seront pas appliquées à l’élément visuel. Toutefois, les applications peuvent répondre aux modifications de style dynamiquement au moment de l’exécution à l’aide de ressources dynamiques.

L’extension DynamicResource de balisage est similaire à l’extension de StaticResource balisage dans laquelle les deux utilisent une clé de dictionnaire pour extraire une valeur d’un ResourceDictionary. Toutefois, pendant que le StaticResource dictionnaire effectue une recherche unique, il DynamicResource conserve un lien vers la clé de dictionnaire. Par conséquent, si l’entrée de dictionnaire associée à la clé est remplacée, la modification est appliquée à l’élément visuel. Cela permet d’apporter des modifications de style d’exécution dans une application.

L’exemple suivant montre des styles dynamiques :

<ContentPage ...>
    <ContentPage.Resources>
        <Style x:Key="baseStyle"
               TargetType="View">
            <Setter Property="VerticalOptions" Value="Center" />
        </Style>
        <Style x:Key="blueSearchBarStyle"
               TargetType="SearchBar"
               BasedOn="{StaticResource baseStyle}">
            <Setter Property="FontAttributes" Value="Italic" />
            <Setter Property="PlaceholderColor" Value="Blue" />
        </Style>
        <Style x:Key="greenSearchBarStyle"
               TargetType="SearchBar">
            <Setter Property="FontAttributes" Value="None" />
            <Setter Property="PlaceholderColor" Value="Green" />
        </Style>
    </ContentPage.Resources>
    <StackLayout>
        <SearchBar Placeholder="SearchBar demonstrating dynamic styles"
                   Style="{DynamicResource blueSearchBarStyle}" />
    </StackLayout>
</ContentPage>

Dans cet exemple, l’objet SearchBar utilise l’extension de DynamicResource balisage pour définir un Style nom blueSearchBarStyle. La SearchBar définition peut ensuite être Style mise à jour dans le code :

Resources["blueSearchBarStyle"] = Resources["greenSearchBarStyle"];

Dans cet exemple, la blueSearchBarStyle définition est mise à jour pour utiliser les valeurs de la greenSearchBarStyle définition. Lorsque ce code est exécuté, il SearchBar est mis à jour pour utiliser les Setter objets définis dans greenSearchBarStyle.

Héritage de style dynamique

La dérivation d’un style à partir d’un style dynamique ne peut pas être obtenue à l’aide de la Style.BasedOn propriété. Au lieu de cela, la classe inclut la BaseResourceKey propriété, qui peut être définie sur une clé de dictionnaire dont la Style valeur peut changer dynamiquement.

L’exemple suivant montre l’héritage de style dynamique :

<ContentPage ...>
    <ContentPage.Resources>
        <Style x:Key="baseStyle"
               TargetType="View">
            <Setter Property="VerticalOptions" Value="Center" />
        </Style>
        <Style x:Key="blueSearchBarStyle"
               TargetType="SearchBar"
               BasedOn="{StaticResource baseStyle}">
            <Setter Property="FontAttributes" Value="Italic" />
            <Setter Property="TextColor" Value="Blue" />
        </Style>
        <Style x:Key="greenSearchBarStyle"
               TargetType="SearchBar">
            <Setter Property="FontAttributes" Value="None" />
            <Setter Property="TextColor" Value="Green" />
        </Style>
        <Style x:Key="tealSearchBarStyle"
               TargetType="SearchBar"
               BaseResourceKey="blueSearchBarStyle">
            <Setter Property="BackgroundColor" Value="Teal" />
            <Setter Property="CancelButtonColor" Value="White" />
        </Style>
    </ContentPage.Resources>
    <StackLayout>
        <SearchBar Text="SearchBar demonstrating dynamic style inheritance"
                   Style="{StaticResource tealSearchBarStyle}" />
    </StackLayout>
</ContentPage>

Dans cet exemple, l’objet SearchBar utilise l’extension de StaticResource balisage pour référencer un Style nom tealSearchBarStyle. Cela Style définit certaines propriétés supplémentaires et utilise la BaseResourceKey propriété pour référencer blueSearchBarStyle. L’extension DynamicResource de balisage n’est pas nécessaire, car tealSearchBarStyle elle ne change pas, à l’exception de celle-ci Style . Par conséquent, tealSearchBarStyle conserve un lien vers et est mis à blueSearchBarStyle jour lorsque le style de base change.

La blueSearchBarStyle définition peut être mise à jour dans le code :

Resources["blueSearchBarStyle"] = Resources["greenSearchBarStyle"];

Dans cet exemple, la blueSearchBarStyle définition est mise à jour pour utiliser les valeurs de la greenSearchBarStyle définition. Lorsque ce code est exécuté, il SearchBar est mis à jour pour utiliser les Setter objets définis dans greenSearchBarStyle.

Classes de style

Les classes de style permettent à plusieurs styles d’être appliqués à un contrôle, sans recourir à l’héritage de style.

Une classe de style peut être créée en définissant la Class propriété sur une Stylestring classe qui représente le nom de la classe. L’avantage que cela offre, par rapport à la définition d’un style explicite à l’aide de l’attribut x:Key , est que plusieurs classes de style peuvent être appliquées à un VisualElement.

Important

Plusieurs styles peuvent partager le même nom de classe, à condition qu’ils ciblent différents types. Cela permet à plusieurs classes de style, qui sont identiquement nommées, de cibler différents types.

L’exemple suivant montre trois BoxView classes de style et une VisualElement classe de style :

<ContentPage ...>
    <ContentPage.Resources>
        <Style TargetType="BoxView"
               Class="Separator">
            <Setter Property="BackgroundColor"
                    Value="#CCCCCC" />
            <Setter Property="HeightRequest"
                    Value="1" />
        </Style>

        <Style TargetType="BoxView"
               Class="Rounded">
            <Setter Property="BackgroundColor"
                    Value="#1FAECE" />
            <Setter Property="HorizontalOptions"
                    Value="Start" />
            <Setter Property="CornerRadius"
                    Value="10" />
        </Style>    

        <Style TargetType="BoxView"
               Class="Circle">
            <Setter Property="BackgroundColor"
                    Value="#1FAECE" />
            <Setter Property="WidthRequest"
                    Value="100" />
            <Setter Property="HeightRequest"
                    Value="100" />
            <Setter Property="HorizontalOptions"
                    Value="Start" />
            <Setter Property="CornerRadius"
                    Value="50" />
        </Style>

        <Style TargetType="VisualElement"
               Class="Rotated"
               ApplyToDerivedTypes="true">
            <Setter Property="Rotation"
                    Value="45" />
        </Style>        
    </ContentPage.Resources>
</ContentPage>

Dans cet exemple, les classes , Roundedet Circle les Separatorclasses de style définissent BoxView chaque propriété sur des valeurs spécifiques. La Rotated classe de style a un TargetType de VisualElement, ce qui signifie qu’elle ne peut être appliquée qu’aux VisualElement instances. Toutefois, sa ApplyToDerivedTypes propriété est définie truesur , ce qui garantit qu’elle peut être appliquée à tous les contrôles dérivés VisualElement, tels que BoxView. Pour plus d’informations sur l’application d’un style à un type dérivé, consultez Appliquer un style aux types dérivés.

Les classes de style peuvent être consommées en définissant la StyleClass propriété du contrôle, qui est de type IList<string>, sur une liste de noms de classes de style. Les classes de style sont appliquées, à condition que le type du contrôle corresponde aux TargetType classes de style.

L’exemple suivant montre trois BoxView instances, chacune définie sur différentes classes de style :

<ContentPage ...>
    <ContentPage.Resources>
        ...
    </ContentPage.Resources>
    <StackLayout>
        <BoxView StyleClass="Separator" />       
        <BoxView WidthRequest="100"
                 HeightRequest="100"
                 HorizontalOptions="Center"
                 StyleClass="Rounded, Rotated" />
        <BoxView HorizontalOptions="Center"
                 StyleClass="Circle" />
    </StackLayout>
</ContentPage>    

Dans cet exemple, le premier BoxView est styleté comme séparateur de traits, tandis que le troisième BoxView est circulaire. La deuxième BoxView a deux classes de style appliquées à elle, qui lui donnent des angles arrondis et la faire pivoter de 45 degrés :

Screenshot of BoxViews styled with style classes.

Important

Plusieurs classes de style peuvent être appliquées à un contrôle, car la StyleClass propriété est de type IList<string>. Lorsque cela se produit, les classes de style sont appliquées dans l’ordre de liste croissant. Par conséquent, lorsque plusieurs classes de style définissent des propriétés identiques, la propriété de la classe de style située à la position de liste la plus élevée est prioritaire.