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 ResourceDictionary style 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 ResourceDictionary fichier peuvent être référencées et appliquées aux éléments à l’aide de l’extension de balisage ou DynamicResource de l’extension StaticResource de balisage. En C#, les ressources peuvent également être définies dans un ResourceDictionary indexeur basé sur des chaînes, puis référencées et appliquées à des éléments.

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 VisualElement objet dérivé a une Resources propriété, qui peut ResourceDictionary contenir des ressources. De même, un Application objet dérivé a une Resources propriété, qui peut ResourceDictionary contenir des ressources.

Une application .NET MAUI ne peut contenir qu’une seule classe qui dérive de Application, mais utilise souvent de nombreuses classes dérivées VisualElement, y compris les pages, les mises en page et les vues. L’un de ces objets peut avoir sa Resources propriété définie sur une ResourceDictionary ressource contenante. Choisir où mettre un impact particulier ResourceDictionary sur les ressources :

  • Les ressources d’un ResourceDictionary élément attaché à une vue, telles que Button ou Label, ne peuvent être appliquées qu’à cet objet particulier.
  • Les ressources d’une ResourceDictionary disposition attachée, telles que StackLayout ou Grid, peuvent être appliquées à la disposition et à tous les enfants de cette disposition.
  • Les ressources d’une ResourceDictionary page définie au niveau de la page peuvent être appliquées à la page et à tous ses enfants.
  • Les ressources d’une ResourceDictionary application définie au niveau de l’application peuvent être appliquées dans l’ensemble de 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éfinies dans un niveau ResourceDictionary d’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 Thickness ressource, plusieurs Color ressources et deux ressources implicites Style .

Important

L’insertion de ressources directement entre les Resources balises d’élément de propriété crée automatiquement un ResourceDictionary objet. Toutefois, il est également valide de placer toutes les ressources entre des balises facultatives ResourceDictionary .

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 de l’extension ResourceDictionary de balisage XAML ou DynamicResource de l’extension StaticResource de balisage XAML.

L’extension StaticResource de balisage est similaire à l’extension DynamicResource de balisage dans laquelle les deux utilisent une clé de dictionnaire pour référencer une valeur à partir d’un dictionnaire de ressources. Toutefois, alors que l’extension de StaticResource balisage effectue une recherche de dictionnaire unique, l’extension de DynamicResource balisage 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 aux ressources d’exécution dans une application. Pour plus d’informations sur les extensions de balisage, consultez les extensions de balisage XAML.

L’exemple XAML suivant montre comment consommer des ressources et définir également 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 PageMargin ressource 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 StackLayout dictionnaire de ressources. Cela entraîne l’apparence affichée dans la capture d’écran suivante :

Consuming resource dictionary resources.

Important

Les ressources spécifiques à une seule page ne doivent pas être incluses dans un dictionnaire de ressources au niveau de l’application, car ces ressources seront ensuite analysées au démarrage de l’application au lieu d’être requises par une page. Pour plus d’informations, consultez Réduire la taille du dictionnaire de ressources d’application.

Comportement de recherche de ressources

Le processus de recherche suivant se produit lorsqu’une ressource est référencée avec l’extension ou DynamicResource l’extension de StaticResource balisage :

  • La clé demandée est case activée ede dans le dictionnaire de ressources, le cas échéant, 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 recherche recherche l’arborescence visuelle vers le haut, case activée 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 une correspondance n’est pas trouvée à l’élément racine, le dictionnaire de ressources au niveau de l’application est examiné.
  • Si une correspondance n’est toujours pas trouvée, une XamlParseException correspondance est levée.

Par conséquent, lorsque l’analyseur XAML rencontre une StaticResource extension ou DynamicResource une extension de balisage, il recherche une clé correspondante en parcourant l’arborescence visuelle en utilisant la première correspondance qu’il trouve. Si cette recherche se termine à la page et que la clé n’a toujours pas été trouvée, l’analyseur XAML recherche l’objet ResourceDictionaryApp attaché. Si la clé est toujours introuvable, une exception est levée.

Remplacer les ressources

Lorsque les ressources partagent des clés, les ressources définies plus bas dans l’arborescence visuelle sont prioritaires sur celles définies plus haut. Par exemple, la définition d’une AppBackgroundColor ressource AliceBlue au niveau de l’application sera remplacée par une ressource au niveau AppBackgroundColor de la page définie sur Teal. De même, une ressource au niveau AppBackgroundColor de la page sera remplacée par une ressource de disposition ou de niveau AppBackgroundColor d’affichage.

Dictionnaires de ressources autonomes

Vous ResourceDictionary pouvez également créer un fichier XAML autonome qui n’est pas sauvegardé par un fichier code-behind. Pour créer un fichier autonome ResourceDictionary, ajoutez un nouveau ResourceDictionary fichier 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 ResourceDictionary balise 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é.

Remarque

Une action autonome ResourceDictionary doit avoir une action de build de MauiXaml.

L’exemple XAML suivant montre un nom autonome ResourceDictionary nommé MyResourceDictionary.xaml :

<?xml version="1.0" encoding="UTF-8" ?>
<?xaml-comp compile="true" ?>
<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 fichier contient une seule ressource, qui est un objet de type DataTemplate. MyResourceDictionary.xaml peut être consommé en le fusionnant dans un autre dictionnaire de ressources.

Fusionner des dictionnaires de ressources

Les dictionnaires de ressources peuvent être combinés en fusionnant un ou plusieurs ResourceDictionary objets dans un autre ResourceDictionary.

Fusionner des dictionnaires de ressources locales

Un fichier local ResourceDictionary peut être fusionné dans un autre ResourceDictionary en créant un ResourceDictionary objet dont Source la propriété est définie sur le nom de fichier XAML avec les ressources :

<ContentPage ...>
    <ContentPage.Resources>
        <!-- Add more resources here -->
        <ResourceDictionary Source="MyResourceDictionary.xaml" />
        <!-- Add more resources here -->
    </ContentPage.Resources>
    ...
</ContentPage>

Cette syntaxe n’instancie pas la MyResourceDictionary classe. Au lieu de cela, il fait référence au fichier XAML. Pour cette raison, lorsque vous définissez la Source propriété, 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 ResourceDictionary.Source propriété ne peut être définie qu’à partir de XAML.

Fusionner des dictionnaires de ressources à partir d’autres assemblys

Une ResourceDictionary peut également être fusionnée dans une autre ResourceDictionary en l’ajoutant à la MergedDictionaries propriété du ResourceDictionary. Cette technique permet aux dictionnaires de ressources d’être fusionnés, quel que soit l’assembly dans lequel ils résident. La fusion de dictionnaires de ressources à partir d’assemblys externes nécessite la ResourceDictionary définition d’une action de génération définie sur MauiXaml, d’avoir un fichier code-behind et de définir l’attribut x:Class dans la balise racine du fichier.

Avertissement

La classe ResourceDictionary définit aussi une propriété MergedWith. Toutefois, cette propriété a été déconseillée et ne doit plus être utilisée.

L’exemple de code suivant montre deux dictionnaires de ressources ajoutés à la MergedDictionaries collection d’un niveau ResourceDictionaryde 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 à partir du même assembly et un dictionnaire de ressources d’un assembly externe sont fusionnés dans le dictionnaire de ressources au niveau de la page. En outre, vous pouvez également ajouter d’autres ResourceDictionary objets dans les MergedDictionaries balises d’élément de propriété et d’autres ressources en dehors de ces balises.

Important

Il ne peut y avoir qu’une MergedDictionaries seule balise d’élément de propriété dans un ResourceDictionary, mais vous pouvez y placer autant d’objets ResourceDictionary que nécessaire.

Lorsque les ressources fusionnées ResourceDictionary partagent des valeurs d’attribut identiques x:Key , .NET MAUI utilise la priorité des ressources suivante :

  1. Ressources locales dans le dictionnaire de ressources.
  2. Les ressources contenues dans les dictionnaires de ressources qui ont été fusionnées via la collection, dans l’ordre MergedDictionaries inverse, sont répertoriées dans la MergedDictionaries propriété.

Conseil

La recherche de dictionnaires de ressources peut être une tâche gourmande en calcul si une application contient plusieurs dictionnaires de ressources volumineux. Par conséquent, pour éviter toute recherche inutile, vous devez vous assurer que chaque page d’une application utilise uniquement des dictionnaires de ressources appropriés à la page.

Utiliser un dictionnaire de ressources XAML à partir du code

Les dictionnaires de ressources définis en XAML peuvent être consommés dans du code, à condition que celui-ci ResourceDictionary soit soutenu par un fichier code-behind. Dans Visual Studio, les fichiers XAML ResourceDictionary sauvegardés par des fichiers code-behind peuvent être ajoutés à votre projet par le modèle d’élément .NET MAUI ResourceDictionary (XAML) :

Screenshot of resource dictionaries backed by code-behind.

Les dictionnaires de ressources XAML sauvegardés par des fichiers code-behind peuvent ensuite être consommés à partir de C# en les ajoutant à la MergedDictionaries collection 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 du code

Vous pouvez accéder aux ressources d’un dictionnaire de ressources à partir de code comme n’importe quel autre dictionnaire.

L’exemple suivant 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;
}

Il s’agit de l’approche recommandée qui garantit que .NET MAUI ne lève pas une KeyNotFoundException ressource si elle ne parvient pas à récupérer une ressource à partir du code. Cela peut se produire lorsqu’un dictionnaire de ressources fusionné est constitué de ressources définies dans un fichier XAML et de ressources inline. Pour plus d’informations, consultez le problème GitHub #11214.

Remarque

Pour récupérer des ressources à l’échelle de l’application à partir du code, accédez au App.Current.Resources dictionnaire de ressources.