Dictionnaires de ressources
Une interface utilisateur d’application multiplateforme .NET (.NET MAUI) ResourceDictionary est un référentiel pour les ressources utilisées par une application .NET MAUI. Les ressources classiques stockées dans un style ResourceDictionary incluent des styles, des modèles de contrôle, des modèles de données, des convertisseurs et des couleurs.
Les ressources XAML stockées dans un fichier ResourceDictionary peuvent être référencées et appliquées aux éléments à l’aide des extensions de balisage StaticResource
ou DynamicResource
. En C#, les ressources peuvent également être définies dans un ResourceDictionary, puis référencées et appliquées à des éléments, à l’aide d’un indexeur basé sur des chaînes.
Conseil
Dans Visual Studio, un fichier XAML ResourceDictionary soutenu par un fichier code-behind peut être ajouté à votre projet par le modèle d’élément .NET MAUI ResourceDictionary (XAML).
Créer des ressources
Chaque objet dérivé VisualElement a une propriété Resources
, qui est un ResourceDictionary pouvant contenir des ressources. De même, un objet dérivé Application
a une propriété Resources
, qui est un ResourceDictionary pouvant contenir des ressources.
Une application .NET MAUI ne peut contenir qu’une seule classe dérivée de Application
, mais utilise souvent de nombreuses classes dérivées de VisualElement, dont des pages, des mises en page et des vues. L’un de ces objets peut avoir sa propriété Resources
définie sur un ResourceDictionary contenant des ressources. Choisir l’emplacement d’un ResourceDictionary a un impact sur l’usage des ressources :
- Les ressources d’un ResourceDictionary attaché à une vue, telles que Button ou Label, ne peuvent être appliquées qu’à cet objet.
- Les ressources d’un ResourceDictionary attaché à une disposition, telles que StackLayout ou Grid, peuvent être appliquées à la disposition et à tous ses enfants.
- Les ressources d’un ResourceDictionary défini au niveau de la page peuvent être appliquées à la page et à tous ses enfants.
- Les ressources d’un ResourceDictionary défini au niveau de l’application peuvent être appliquées à toute l’application.
À l’exception des styles implicites, chaque ressource du dictionnaire de ressources doit avoir une clé de chaîne unique définie avec l’attribut x:Key
.
Le code XAML suivant montre les ressources d’un ResourceDictionary défini au niveau de l’application dans le fichier App.xaml :
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ResourceDictionaryDemo.App">
<Application.Resources>
<Thickness x:Key="PageMargin">20</Thickness>
<!-- Colors -->
<Color x:Key="AppBackgroundColor">AliceBlue</Color>
<Color x:Key="NavigationBarColor">#1976D2</Color>
<Color x:Key="NavigationBarTextColor">White</Color>
<Color x:Key="NormalTextColor">Black</Color>
<!-- Images -->
<x:String x:Key="BackgroundImage">background</x:String>
<x:String x:Key="MenuIcon">menu.png</x:String>
<x:String x:Key="SearchIcon">search.png</x:String>
<!-- Implicit styles -->
<Style TargetType="NavigationPage">
<Setter Property="BarBackgroundColor"
Value="{StaticResource NavigationBarColor}" />
<Setter Property="BarTextColor"
Value="{StaticResource NavigationBarTextColor}" />
</Style>
<Style TargetType="ContentPage"
ApplyToDerivedTypes="True">
<Setter Property="BackgroundColor"
Value="{StaticResource AppBackgroundColor}" />
</Style>
</Application.Resources>
</Application>
Dans cet exemple, le dictionnaire de ressources définit une ressource Thickness
, plusieurs ressources Color et deux ressources implicites Style.
Important
L’insertion de ressources directement entre les balises d’élément de propriété Resources
crée automatiquement un objet ResourceDictionary. Toutefois, il est également possible de placer toutes les ressources entre des balises ResourceDictionary facultatives.
Consommer des ressources
Chaque ressource a une clé spécifiée à l’aide de l’attribut x:Key
, qui devient sa clé de dictionnaire dans le ResourceDictionary. La clé est utilisée pour référencer une ressource à partir du ResourceDictionary avec l’extension de balisage XAML StaticResource
ou DynamicResource
.
L’extension de balisage StaticResource
est similaire à l’extension DynamicResource
en ce que toutes les deux utilisent une clé de dictionnaire pour extraire une valeur d’un dictionnaire de ressources. Toutefois, alors que l’extension de balisage StaticResource
effectue une seule recherche dans le dictionnaire, l’extension 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 ressources d’exécution dans une application. Pour plus d’informations sur les extensions de balisage, consultez Extensions de balisage XAML.
L’exemple XAML suivant montre comment consommer des ressources, et définir une ressource supplémentaire dans un StackLayout :
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ResourceDictionaryDemo.MainPage"
Title="Main page">
<StackLayout Margin="{StaticResource PageMargin}"
Spacing="6">
<StackLayout.Resources>
<!-- Implicit style -->
<Style TargetType="Button">
<Setter Property="FontSize" Value="14" />
<Setter Property="BackgroundColor" Value="#1976D2" />
<Setter Property="TextColor" Value="White" />
<Setter Property="CornerRadius" Value="5" />
</Style>
</StackLayout.Resources>
<Label Text="This app demonstrates consuming resources that have been defined in resource dictionaries." />
<Button Text="Navigate"
Clicked="OnNavigateButtonClicked" />
</StackLayout>
</ContentPage>
Dans cet exemple, l’objet ContentPage consomme le style implicite défini dans le dictionnaire de ressources au niveau de l’application. L’objet StackLayout consomme la ressource PageMargin
définie dans le dictionnaire de ressources au niveau de l’application, tandis que l’objet Button consomme le style implicite défini dans le dictionnaire de ressources StackLayout. Cela donne la vue illustrée par les captures d’écran suivantes :
Important
Les ressources spécifiques à une page ne doivent pas être incluses dans un dictionnaire de ressources défini au niveau de l’application, car les ressources sont alors analysées au démarrage de l’application et non lorsqu’une page le demande. Pour plus d’informations, consultez Réduire la taille du dictionnaire de ressources de l’application.
Comportement de la recherche de ressources
Le processus de recherche suivant se produit lorsqu’une ressource est référencée avec l’extension de balisage StaticResource
ou DynamicResource
:
- La clé demandée est recherchée dans le dictionnaire de ressources, s’il existe, pour l’élément qui définit la propriété. Si la clé demandée est trouvée, sa valeur est retournée et le processus de recherche se termine.
- Si aucune correspondance n’est trouvée, le processus de recherche explore l’arborescence d’éléments visuels vers le haut, en vérifiant le dictionnaire de ressources de chaque élément parent. Si la clé demandée est trouvée, sa valeur est retournée et le processus de recherche se termine. Sinon, le processus continue vers le haut jusqu’à ce que l’élément racine soit atteint.
- Si aucune correspondance n’est trouvée au niveau de l’élément racine, le dictionnaire de ressources au niveau de l’application est examiné.
- Si aucune correspondance n’est trouvée, une exception
XamlParseException
est retournée.
Par conséquent, lorsque l’analyseur XAML rencontre une extension de balisage StaticResource
ou DynamicResource
, il recherche une clé correspondante en parcourant l’arborescence d’éléments visuels jusqu’à trouver une correspondance. Si cette recherche atteint la page et que la clé n’a toujours pas été trouvée, l’analyseur XAML recherche le ResourceDictionary attaché à l’objet App
. Si la clé est toujours introuvable, une exception est retournée.
Remplacer des ressources
Lorsque des ressources ont la même clé, les ressources définies plus bas dans l’arborescence visuelle sont prioritaires sur celles définies plus haut. Par exemple, une ressource AppBackgroundColor
définie sur AliceBlue
au niveau de l’application sera remplacée par une ressource AppBackgroundColor
définie sur Teal
au niveau de la page. De même, une ressource AppBackgroundColor
définie au niveau de la page sera remplacée par une ressource AppBackgroundColor
définie au niveau de la disposition ou de la vue.
Dictionnaires de ressources autonomes
Un ResourceDictionary peut également être créé en tant que fichier XAML autonome non soutenu par un fichier code-behind. Pour créer un ResourceDictionary autonome, ajoutez un nouveau fichier ResourceDictionary au projet avec le modèle d’élément .NET MAUI ResourceDictionary (XAML) et supprimez son fichier code-behind. Ensuite, dans le fichier XAML, supprimez l’attribut x:Class
de la balise ResourceDictionary près du début du fichier. En outre, ajoutez <?xaml-comp compile="true" ?>
après l’en-tête XML pour vous assurer que le code XAML sera compilé.
Un ResourceDictionary peut également être créé en tant que fichier XAML autonome non soutenu par un fichier code-behind. Pour créer un ResourceDictionary autonome, ajoutez un nouveau fichier ResourceDictionary au projet avec le modèle d’élément .NET MAUI ResourceDictionary (XAML) et supprimez son fichier code-behind. Ensuite, dans le fichier XAML, supprimez l’attribut x:Class
de la balise ResourceDictionary près du début du fichier. Par défaut, le code XAML d’un ResourceDictionary autonome est compilé, sauf si <?xaml-comp compile="false" ?>
est spécifié après l’en-tête XML.
Remarque
Un ResourceDictionary autonome doit avoir une action de build de MauiXaml.
L’exemple XAML suivant montre un ResourceDictionary autonome nommé MyResourceDictionary.xaml :
<?xml version="1.0" encoding="UTF-8" ?>
<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<DataTemplate x:Key="PersonDataTemplate">
<ViewCell>
<Grid RowSpacing="6"
ColumnSpacing="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.2*" />
<ColumnDefinition Width="0.3*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding Name}"
TextColor="{StaticResource NormalTextColor}"
FontAttributes="Bold" />
<Label Grid.Column="1"
Text="{Binding Age}"
TextColor="{StaticResource NormalTextColor}" />
<Label Grid.Column="2"
Text="{Binding Location}"
TextColor="{StaticResource NormalTextColor}"
HorizontalTextAlignment="End" />
</Grid>
</ViewCell>
</DataTemplate>
</ResourceDictionary>
Dans cet exemple, le ResourceDictionary contient une seule ressource, qui est un objet de type DataTemplate. MyResourceDictionary.xaml peut être consommé en le fusionnant avec un autre dictionnaire de ressources.
Fusionner des dictionnaires de ressources
Des dictionnaires de ressources peuvent être combinés en fusionnant un ou plusieurs objets ResourceDictionary dans un autre ResourceDictionary.
Fusionner des dictionnaires de ressources locales
Un fichier ResourceDictionary local peut être fusionné à un autre ResourceDictionary en créant un objet ResourceDictionary dont la propriété Source
est définie sur le nom de fichier XAML avec les ressources suivantes :
<ContentPage ...>
<ContentPage.Resources>
<!-- Add more resources here -->
<ResourceDictionary Source="MyResourceDictionary.xaml" />
<!-- Add more resources here -->
</ContentPage.Resources>
...
</ContentPage>
Cette syntaxe n’instancie pas la classe MyResourceDictionary
. À la place, elle fait référence au fichier XAML. Pour cette raison, lorsque vous définissez la propriété Source
, un fichier code-behind n’est pas obligatoire et l’attribut x:Class
peut être supprimé de la balise racine du fichier MyResourceDictionary.xaml.
Important
La propriété ResourceDictionary.Source
ne peut être définie qu’à partir de XAML.
Fusionner des dictionnaires de ressources à partir d’autres assemblys
Un ResourceDictionary peut également être fusionné à un autre ResourceDictionary en l’ajoutant à la propriété MergedDictionaries
du ResourceDictionary. Cette technique permet de fusionner des dictionnaires de ressources, quel que soit l’assembly dans lequel ils se trouvent. La fusion de dictionnaires de ressources à partir d’assemblys externes nécessite que le ResourceDictionary dispose d’une action de build définie sur MauiXaml, d’un fichier code-behind et d’un attribut x:Class
défini dans la balise racine du fichier.
Avertissement
La classe ResourceDictionary définit aussi une propriété MergedWith
. Toutefois, cette propriété est déconseillée et ne doit plus être utilisée.
L’exemple de code suivant montre deux dictionnaires de ressources ajoutés à la collection MergedDictionaries
d’un ResourceDictionary défini au niveau de la page :
<ContentPage ...
xmlns:local="clr-namespace:ResourceDictionaryDemo"
xmlns:theme="clr-namespace:MyThemes;assembly=MyThemes">
<ContentPage.Resources>
<ResourceDictionary>
<!-- Add more resources here -->
<ResourceDictionary.MergedDictionaries>
<!-- Add more resource dictionaries here -->
<local:MyResourceDictionary />
<theme:DefaultTheme />
<!-- Add more resource dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<!-- Add more resources here -->
</ResourceDictionary>
</ContentPage.Resources>
...
</ContentPage>
Dans cet exemple, un dictionnaire de ressources provenant du même assembly et un dictionnaire de ressources provenant d’un assembly externe sont fusionnés avec le dictionnaire de ressources défini au niveau de la page. En outre, vous pouvez ajouter d’autres objets ResourceDictionary dans les balises d’élément de propriété MergedDictionaries
et d’autres ressources en dehors de ces balises.
Important
Il ne peut y avoir qu’une seule balise d’élément de propriété MergedDictionaries
dans un ResourceDictionary, mais vous pouvez y placer autant d’objets ResourceDictionary que nécessaire.
Lorsque des ressources ResourceDictionary fusionnées partagent des valeurs d’attribut x:Key
identiques, .NET MAUI considère les ressources avec l’ordre de priorité suivant :
- Ressources liées localement au dictionnaire de ressources.
- Ressources contenues dans les dictionnaires de ressources qui ont été fusionnés via la collection
MergedDictionaries
, dans l’ordre inverse de leur listage dans la propriétéMergedDictionaries
.
Conseil
Effectuer des recherches au sein de dictionnaires de ressources peut demander beaucoup de calculs si une application contient plusieurs dictionnaires de ressources volumineux. Par conséquent, pour éviter des recherches inutiles, assurez-vous que chaque page d’une application utilise uniquement des dictionnaires de ressources appropriés.
Consommer un dictionnaire de ressources XAML à partir de code
Les dictionnaires de ressources définis en XAML peuvent être consommés en code, à condition que le ResourceDictionary soit soutenu par un fichier code-behind. Dans Visual Studio, les fichiers XAML ResourceDictionary soutenus par des fichiers code-behind peuvent être ajoutés à votre projet par le modèle d’élément .NET MAUI ResourceDictionary (XAML) :
Les dictionnaires de ressources XAML soutenus par des fichiers code-behind peuvent ensuite être consommés à partir de C# en les ajoutant à la collection MergedDictionaries du dictionnaire de ressources :
Resources.MergedDictionaries.Add(new MyMauiApp.Resources.Styles.MyColors());
Resources.MergedDictionaries.Add(new MyMauiApp.Resources.Styles.MyStyles());
Accéder aux ressources par clé à partir de code
Vous pouvez accéder aux ressources d’un dictionnaire de ressources à partir de code comme vous le feriez avec n’importe quel autre dictionnaire.
Cet exemple montre comment récupérer et appliquer une ressource à partir du dictionnaire de ressources d’une page :
// Retrieve the Primary color value which is in the page's resource dictionary
var hasValue = Resources.TryGetValue("Primary", out object primaryColor);
if (hasValue)
{
myLabel.TextColor = (Color)primaryColor;
}
Cette approche est recommandée car elle garantit que .NET MAUI ne retournera pas une exception KeyNotFoundException
s’il ne parvient pas à récupérer une ressource à partir de code. Cela peut se produire lorsqu’un dictionnaire de ressources fusionné est constitué de ressources définies dans un fichier XAML et de ressources incluses. Pour plus d’informations, consultez le problème GitHub #11214.
Remarque
Pour récupérer des ressources à l’échelle de l’application à partir de code, accédez au dictionnaire de ressources App.Current.Resources
.