Extensions de balisage XAML
Les extensions de balisage XAML .NET Multi-platform App UI (.NET MAUI) permettent de définir des propriétés sur des objets ou des valeurs référencés indirectement à partir d’autres sources. Les extensions de balisage XAML sont particulièrement importantes pour partager des objets et référencer des constantes utilisées dans une application, mais leur utilité première consiste à effectuer la liaison de données.
En règle générale, XAML sert à attribuer des valeurs explicites aux propriétés d’un objet, telles qu’une chaîne, un nombre, un membre d’énumération ou une chaîne qui est convertie en valeur en arrière-plan. Toutefois, il arrive que les propriétés doivent prendre des valeurs définies ailleurs, ou qui peuvent nécessiter un peu de traitement par code au moment de l’exécution. C’est à cela que servent les extensions de balisage XAML.
Les extensions de balisage XAML sont ainsi nommées car elles sont soutenues par du code dans des classes qui implémentent IMarkupExtension. Il est également possible d’écrire vos propres extensions de balisage personnalisées.
Le plus souvent, les extensions de balisage XAML sont instantanément reconnaissables dans les fichiers XAML, car elles apparaissent sous forme de valeurs d’attribut délimitées par des accolades, { et }, mais il arrive que des extensions de balisage soient présentes dans le balisage en tant qu’éléments conventionnels.
Important
Les extensions de balisage peuvent avoir des propriétés, mais elles ne sont pas définies comme des attributs XML. Dans une extension de balisage, les paramètres de propriété sont séparés par des virgules et aucun guillemet n’apparaît dans les accolades.
Ressources partagées
Certaines pages XAML contiennent plusieurs vues avec des propriétés définies sur les mêmes valeurs. Par exemple, la plupart des paramètres de propriété de ces objets Button sont les mêmes :
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.SharedResourcesPage"
Title="Shared Resources Page">
<StackLayout>
<Button Text="Do this!"
HorizontalOptions="Center"
VerticalOptions="Center"
BorderWidth="3"
Rotation="-15"
TextColor="Red"
FontSize="24" />
<Button Text="Do that!"
HorizontalOptions="Center"
VerticalOptions="Center"
BorderWidth="3"
Rotation="-15"
TextColor="Red"
FontSize="24" />
<Button Text="Do the other thing!"
HorizontalOptions="Center"
VerticalOptions="Center"
BorderWidth="3"
Rotation="-15"
TextColor="Red"
FontSize="24" />
</StackLayout>
</ContentPage>
Si l’une de ces propriétés doit être modifiée, vous préférerez peut-être apporter la modification une seule fois au lieu de trois fois. S’il s’agissait de code, vous utiliseriez probablement des constantes et des objets statiques en lecture seule pour vous aider à maintenir ces valeurs cohérentes et faciles à modifier.
En XAML, une solution populaire consiste à stocker ces valeurs ou objets dans un dictionnaire de ressources. La classe VisualElement définit une propriété nommée Resources
de type ResourceDictionary, qui est un dictionnaire avec des clés de type string
et des valeurs de type object
. Vous pouvez placer des objets dans ce dictionnaire, puis les référencer à partir du balisage, le tout en XAML.
Pour utiliser un dictionnaire de ressources sur une page, incluez une paire de balises d’élément de propriété Resources
en haut de la page et ajoutez des ressources dans ces balises. Il est possible d’ajouter des objets et des valeurs de tous types à un dictionnaire de ressources. Ces types doivent être instanciables. Il ne peut pas s’agir de classes abstraites, par exemple. Ils doivent également avoir un constructeur sans paramètre public. Chaque élément nécessite une clé de dictionnaire spécifiée avec l’attribut x:Key
:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.SharedResourcesPage"
Title="Shared Resources Page">
<ContentPage.Resources>
<LayoutOptions x:Key="horzOptions"
Alignment="Center" />
<LayoutOptions x:Key="vertOptions"
Alignment="Center" />
</ContentPage.Resources>
...
</ContentPage>
Dans cet exemple, les deux ressources sont des valeurs de type de structure LayoutOptions
, et chacune a une clé unique et une ou deux propriétés définies. En matière de code et de balisage, il est beaucoup plus courant d’utiliser les champs statiques de LayoutOptions
, mais ici, il est plus pratique de définir les propriétés.
Remarque
Des balises ResourceDictionary facultatives peuvent être incluses en tant qu’enfants des balises Resources
.
Les ressources peuvent ensuite être consommées par les objets Button, à l’aide de l’extension de balisage XAML StaticResource
pour définir leurs propriétés HorizontalOptions
et VerticalOptions
:
<Button Text="Do this!"
HorizontalOptions="{StaticResource horzOptions}"
VerticalOptions="{StaticResource vertOptions}"
BorderWidth="3"
Rotation="-15"
TextColor="Red"
FontSize="24" />
L’extension de balisage StaticResource
est toujours délimitée par des accolades et inclut la clé de dictionnaire. Le nom StaticResource
la distingue de DynamicResource
, que .NET MAUI prend également en charge. DynamicResource
est destiné aux clés de dictionnaire associées à des valeurs susceptibles de changer au moment de l’exécution, alors que StaticResource
accède aux éléments du dictionnaire une seule fois lorsque les éléments de la page sont construits. Chaque fois que l’analyseur XAML rencontre une extension de balisage StaticResource
, il recherche l’arborescence d’éléments visuels et utilise le premier ResourceDictionary qui contient cette clé.
Il est nécessaire de stocker des doubles dans le dictionnaire pour les propriétés BorderWidth
, Rotation
et FontSize
. XAML définit fort opportunément des balises pour les types de données courants comme x:Double
et x:Int32
:
<ContentPage.Resources>
<LayoutOptions x:Key="horzOptions"
Alignment="Center" />
<LayoutOptions x:Key="vertOptions"
Alignment="Center" />
<x:Double x:Key="borderWidth">3</x:Double>
<x:Double x:Key="rotationAngle">-15</x:Double>
<x:Double x:Key="fontSize">24</x:Double>
</ContentPage.Resources>
Ces trois ressources supplémentaires peuvent être référencées de la même façon que les valeurs LayoutOptions
:
<Button Text="Do this!"
HorizontalOptions="{StaticResource horzOptions}"
VerticalOptions="{StaticResource vertOptions}"
BorderWidth="{StaticResource borderWidth}"
Rotation="{StaticResource rotationAngle}"
TextColor="Red"
FontSize="{StaticResource fontSize}" />
Pour les ressources de type Color, vous pouvez utiliser les mêmes représentations sous forme de chaîne que lors de l’attribution directe d’attributs de ces types. Les convertisseurs de type inclus dans .NET MAUI sont appelés lors de la création de la ressource. Il est également possible d’utiliser la classe OnPlatform
dans le dictionnaire de ressources pour définir différentes valeurs pour les plateformes. L’exemple suivant utilise cette classe pour définir différentes couleurs de texte :
<OnPlatform x:Key="textColor"
x:TypeArguments="Color">
<On Platform="iOS" Value="Red" />
<On Platform="Android" Value="Aqua" />
</OnPlatform>
La ressource OnPlatform
hérite d’un attribut x:Key
car il s’agit d’un objet du dictionnaire, et d’un attribut x:TypeArguments
car il s’agit d’une classe générique. Les attributs iOS
et Android
sont convertis en valeurs Color lorsque l’objet est initialisé.
L’exemple suivant montre les trois boutons accédant à six valeurs partagées :
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.SharedResourcesPage"
Title="Shared Resources Page">
<ContentPage.Resources>
<LayoutOptions x:Key="horzOptions"
Alignment="Center" />
<LayoutOptions x:Key="vertOptions"
Alignment="Center" />
<x:Double x:Key="borderWidth">3</x:Double>
<x:Double x:Key="rotationAngle">-15</x:Double>
<x:Double x:Key="fontSize">24</x:Double>
<OnPlatform x:Key="textColor"
x:TypeArguments="Color">
<On Platform="iOS" Value="Red" />
<On Platform="Android" Value="Aqua" />
<On Platform="WinUI" Value="#80FF80" />
</OnPlatform>
</ContentPage.Resources>
<StackLayout>
<Button Text="Do this!"
HorizontalOptions="{StaticResource horzOptions}"
VerticalOptions="{StaticResource vertOptions}"
BorderWidth="{StaticResource borderWidth}"
Rotation="{StaticResource rotationAngle}"
TextColor="{StaticResource textColor}"
FontSize="{StaticResource fontSize}" />
<Button Text="Do that!"
HorizontalOptions="{StaticResource horzOptions}"
VerticalOptions="{StaticResource vertOptions}"
BorderWidth="{StaticResource borderWidth}"
Rotation="{StaticResource rotationAngle}"
TextColor="{StaticResource textColor}"
FontSize="{StaticResource fontSize}" />
<Button Text="Do the other thing!"
HorizontalOptions="{StaticResource horzOptions}"
VerticalOptions="{StaticResource vertOptions}"
BorderWidth="{StaticResource borderWidth}"
Rotation="{StaticResource rotationAngle}"
TextColor="{StaticResource textColor}"
FontSize="{StaticResource fontSize}" />
</StackLayout>
</ContentPage>
La capture d’écran suivante permet de vérifier la cohérence du style :
Bien qu’il soit courant de définir la collection Resources
en haut de la page, vous pouvez avoir des collections Resources
sur d’autres éléments de la page. L’exemple suivant montre comment ajouter Resources à un StackLayout :
<StackLayout>
<StackLayout.Resources>
<Color x:Key="textColor">Blue</Color>
</StackLayout.Resources>
...
</StackLayout>
L’un des types d’objets les plus couramment stockés dans les dictionnaires de ressources est le Style MAUI.NET, qui définit une collection de paramètres de propriété. Pour plus d’informations sur les styles, consultez Appliquer un style aux applications en utilisant XAML.
Remarque
L’objectif d’un dictionnaire de ressources est de partager des objets. Par conséquent, il n’est pas judicieux de placer des contrôles tels qu’un Label ou un Button dans un dictionnaire de ressources. Les éléments visuels ne peuvent pas être partagés, car la même instance ne peut pas apparaître deux fois sur une page.
x:Static, extension de balisage
Outre l’extension de balisage StaticResource
, il existe également une extension de balisage x:Static
. Toutefois, alors que StaticResource
retourne un objet à partir d’un dictionnaire de ressources, x:Static
accède à un champ statique public, à une propriété statique publique, à un champ constant public ou à un membre d’énumération.
Remarque
L’extension de balisage StaticResource
est prise en charge par les implémentations XAML qui définissent un dictionnaire de ressources, tandis que x:Static
fait intrinsèquement partie de XAML, comme le révèle le préfixe x
.
L’exemple suivant montre comment x:Static
permet de référencer explicitement des champs statiques et des membres d’énumération :
<Label Text="Hello, XAML!"
VerticalOptions="{x:Static LayoutOptions.Start}"
HorizontalTextAlignment="{x:Static TextAlignment.Center}"
TextColor="{x:Static Colors.Aqua}" />
L’utilisation principale de l’extension de balisage x:Static
consiste à référencer des champs ou des propriétés statiques à partir de votre propre code. Par exemple, voici une classe AppConstants
qui contient des champs statiques que vous pouvez utiliser sur plusieurs pages dans une application :
namespace XamlSamples
{
static class AppConstants
{
public static readonly Color BackgroundColor = Colors.Aqua;
public static readonly Color ForegroundColor = Colors.Brown;
}
}
Pour référencer les champs statiques de cette classe dans un fichier XAML, vous devez utiliser une déclaration d’espace de noms XML afin d’indiquer où se trouve ce fichier. Chaque déclaration d’espace de noms XML supplémentaire définit un nouveau préfixe. Pour accéder aux classes liées localement à l’espace de noms de l’application racine, telles que AppConstants
, vous pouvez utiliser le préfixe local
. La déclaration d’espace de noms doit indiquer le nom de l’espace de noms CLR (Common Language Runtime), également appelé nom d’espace de noms .NET, qui est le nom qui apparaît dans une définition namespace
C# ou dans une directive using
:
xmlns:local="clr-namespace:XamlSamples"
Vous pouvez également définir des déclarations d’espace de noms XML pour les espaces de noms .NET. Par exemple, voici un préfixe sys
pour l’espace de noms System
.NET standard, qui se trouve dans l’assembly netstandard
. Comme il s’agit d’un autre assembly, vous devez également spécifier le nom de l’assembly ; en l’occurence, netstandard
:
xmlns:sys="clr-namespace:System;assembly=netstandard"
Remarque
Le mot clé clr-namespace
est suivi d’un double point, puis du nom de l’espace de noms .NET, suivi d’un point-virgule, du mot clé assembly
, d’un signe égal et du nom de l’assembly.
Les champs statiques peuvent ensuite être consommés après avoir déclaré l’espace de noms XML :
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XamlSamples"
xmlns:sys="clr-namespace:System;assembly=netstandard"
x:Class="XamlSamples.StaticConstantsPage"
Title="Static Constants Page"
Padding="5,25,5,0">
<StackLayout>
<Label Text="Hello, XAML!"
TextColor="{x:Static local:AppConstants.BackgroundColor}"
BackgroundColor="{x:Static local:AppConstants.ForegroundColor}"
FontAttributes="Bold"
FontSize="30"
HorizontalOptions="Center" />
<BoxView WidthRequest="{x:Static sys:Math.PI}"
HeightRequest="{x:Static sys:Math.E}"
Color="{x:Static local:AppConstants.ForegroundColor}"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Scale="100" />
</StackLayout>
</ContentPage>
Dans cet exemple, les dimensions BoxView sont définies sur Math.PI
et Math.E
mais agrandies d’un facteur 100 :
Autres extensions de balisage
Plusieurs extensions de balisage sont intrinsèques au code XAML et prises en charge dans .NET MAUI XAML. Certaines ne sont pas utilisées souvent, mais sont essentielles quand le besoin s’en fait sentir :
- Si une propriété a une valeur non-
null
par défaut, mais que vous souhaitez la définir surnull
, définissez-la sur l’extension de balisage{x:Null}
. - Si une propriété est de type
Type
, vous pouvez l’affecter à un objetType
à l’aide de l’extension de balisage{x:Type someClass}
. - Vous pouvez définir des tableaux en XAML à l’aide de l’extension de balisage
x:Array
. Cette extension de balisage a un attribut obligatoire nomméType
qui indique le type des éléments dans le tableau.
Pour plus d’informations sur les extensions de balisage XAML, consultez Utiliser des extensions de balisage XAML.
Étapes suivantes
Les liaisons de données .NET MAUI permettent de lier les propriétés de deux objets afin que toute modification d’un objet entraîne la modification de l’autre.