Partager via


Références aux ressources ResourceDictionary et XAML

Vous pouvez définir l’interface utilisateur ou les ressources de votre application à l’aide de XAML. Les ressources sont généralement des définitions d’un objet que vous prévoyez d’utiliser plusieurs fois. Pour faire référence à une ressource XAML ultérieurement, vous spécifiez une clé pour une ressource qui agit comme son nom. Vous pouvez référencer une ressource dans une application ou à partir d’une page XAML dans celle-ci. Vous pouvez définir vos ressources à l’aide d’un élément ResourceDictionary à partir du code XAML Windows Runtime. Vous pouvez ensuite référencer vos ressources à l’aide d’une l’extension de balisage StaticResource ou extension de balisage ThemeResource.

Les éléments XAML que vous pouvez déclarer le plus souvent en tant que ressources XAML incluent style, ControlTemplate, les composants d’animation et les sous-classes Pinceau. Ici, nous expliquons comment définir une ResourceDictionary et des ressources clés, et comment les ressources XAML se rapportent à d’autres ressources que vous définissez dans le cadre de votre application ou package d’application. Nous expliquons également les fonctionnalités avancées du dictionnaire de ressources telles que MergedDictionaries et ThemeDictionaries.

Conditions préalables

Une bonne compréhension du balisage XAML. Nous vous recommandons de lire l'aperçu XAML .

Définir et utiliser des ressources XAML

Les ressources XAML sont des objets référencés à partir du balisage plusieurs fois. Les ressources sont définies dans un ResourceDictionary, généralement dans un fichier distinct ou en haut de la page de balisage, comme ceci.

<Page
    x:Class="MSDNSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Page.Resources>
        <x:String x:Key="greeting">Hello world</x:String>
        <x:String x:Key="goodbye">Goodbye world</x:String>
    </Page.Resources>

    <TextBlock Text="{StaticResource greeting}" Foreground="Gray" VerticalAlignment="Center"/>
</Page>

Dans cet exemple :

  • <Page.Resources>…</Page.Resources> : définit le dictionnaire de ressources.
  • <x:String> - Définit la ressource avec la clé « message d’accueil ».
  • {StaticResource greeting} - Recherche la ressource avec la clé « greeting », qui est assignée à la propriété Text de l'élément TextBlock.

Remarque Ne confondez pas les concepts liés à ResourceDictionary avec l’action de construction de la ressource, les fichiers de ressource (.resw) ou d’autres « ressources » abordés dans le contexte de la structure du projet de code qui produit votre package d’application.

Les ressources n’ont pas besoin d’être des chaînes ; il peut s’agir de n’importe quel objet partageable, tel que les styles, les modèles, les pinceaux et les couleurs. Toutefois, les contrôles, les formes et d’autres FrameworkElementne sont pas partageables, de sorte qu’ils ne peuvent pas être déclarés comme des ressources réutilisables. Pour plus d’informations sur le partage, consultez la section Les ressources XAML doivent être partageables située plus loin dans cette rubrique.

Ici, un pinceau et une chaîne sont déclarés en tant que ressources et utilisés par les contrôles d’une page.

<Page
    x:Class="SpiderMSDN.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Page.Resources>
        <SolidColorBrush x:Key="myFavoriteColor" Color="green"/>
        <x:String x:Key="greeting">Hello world</x:String>
    </Page.Resources>

    <TextBlock Foreground="{StaticResource myFavoriteColor}" Text="{StaticResource greeting}" VerticalAlignment="Top"/>
    <Button Foreground="{StaticResource myFavoriteColor}" Content="{StaticResource greeting}" VerticalAlignment="Center"/>
</Page>

Toutes les ressources doivent avoir une clé. Généralement, cette clé est une chaîne définie avec x:Key="myString". Toutefois, il existe plusieurs autres façons de spécifier une clé :

  • Style et ControlTemplate nécessitent un TargetType, et utiliseront le TargetType comme clé si x:Key n’est pas spécifié. Dans ce cas, la clé est l’objet Type réel, et non une chaîne. (Voir les exemples ci-dessous)
  • les ressources DataTemplate qui ont un TargetType utiliseront le TargetType comme clé si x:Key n’est pas spécifié. Dans ce cas, la clé est l’objet Type réel, et non une chaîne.
  • x:Name peut être utilisé au lieu de x:Key. Toutefois, x :Name génère également un champ code-behind pour la ressource. Par conséquent, x :Name est moins efficace que x :Key, car ce champ doit être initialisé lors du chargement de la page.

L’extension de balisage StaticResource ne peut récupérer des ressources qu’avec un nom de chaîne (x :Key ou x :Name). Toutefois, l’infrastructure XAML recherche également des ressources de style implicites (celles qui utilisent TargetType plutôt que x :Key ou x :Name) lorsqu’elle décide du style et du modèle à utiliser pour un contrôle qui n’a pas défini les propriétés Style et ContentTemplate ou ItemTemplate.

Ici, le style a une clé implicite de typeof(Button), et depuis que le bouton en bas de la page ne spécifie pas de propriété Style, il recherche un style avec une touche de typeof(Button):

<Page
    x:Class="MSDNSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Page.Resources>
        <Style TargetType="Button">
            <Setter Property="Background" Value="Red"/>
        </Style>
    </Page.Resources>
    <Grid>
       <!-- This button will have a red background. -->
       <Button Content="Button" Height="100" VerticalAlignment="Center" Width="100"/>
    </Grid>
</Page>

Pour plus d’informations sur les styles implicites et leur fonctionnement, consultez contrôles de style et modèles de contrôle.

Rechercher des ressources dans le code

Vous accédez aux membres du dictionnaire de ressources comme n’importe quel autre dictionnaire.

Avertissement

Lorsque vous effectuez une recherche de ressources dans le code, seules les ressources du dictionnaire Page.Resources sont examinées. Contrairement à l’extension de balisage staticResource , le code ne revient pas au dictionnaire Application.Resources si les ressources ne sont pas trouvées dans le premier dictionnaire.

 

Cet exemple montre comment récupérer la ressource redButtonStyle à partir du dictionnaire de ressources d’une page :

<Page
    x:Class="MSDNSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Page.Resources>
        <Style TargetType="Button" x:Key="redButtonStyle">
            <Setter Property="Background" Value="red"/>
        </Style>
    </Page.Resources>
</Page>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            Style redButtonStyle = (Style)this.Resources["redButtonStyle"];
        }
    }
    MainPage::MainPage()
    {
        InitializeComponent();
        Windows::UI::Xaml::Style style = Resources().TryLookup(winrt::box_value(L"redButtonStyle")).as<Windows::UI::Xaml::Style>();
    }

Pour rechercher des ressources à l’échelle de l’application à partir du code, utilisez Application.Current.Resources pour obtenir le dictionnaire de ressources de l’application, comme illustré ici.

<Application
    x:Class="MSDNSample.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:SpiderMSDN">
    <Application.Resources>
        <Style TargetType="Button" x:Key="appButtonStyle">
            <Setter Property="Background" Value="red"/>
        </Style>
    </Application.Resources>

</Application>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            Style appButtonStyle = (Style)Application.Current.Resources["appButtonStyle"];
        }
    }
    MainPage::MainPage()
    {
        InitializeComponent();
        Windows::UI::Xaml::Style style = Application::Current().Resources()
                                                               .TryLookup(winrt::box_value(L"appButtonStyle"))
                                                               .as<Windows::UI::Xaml::Style>();
    }

Vous pouvez également ajouter une ressource d’application dans le code.

Il y a deux choses à garder à l’esprit lors de cette opération.

  • Tout d’abord, vous devez ajouter les ressources avant toute page tente d’utiliser la ressource.
  • Ensuite, vous ne pouvez pas ajouter de ressources dans le constructeur de l’application.

Vous pouvez éviter les deux problèmes si vous ajoutez la ressource dans la méthode Application.OnLaunched, comme ceci.

// App.xaml.cs
    
sealed partial class App : Application
{
    protected override void OnLaunched(LaunchActivatedEventArgs e)
    {
        Frame rootFrame = Window.Current.Content as Frame;
        if (rootFrame == null)
        {
            SolidColorBrush brush = new SolidColorBrush(Windows.UI.Color.FromArgb(255, 0, 255, 0)); // green
            this.Resources["brush"] = brush;
            // … Other code that VS generates for you …
        }
    }
}
// App.cpp

void App::OnLaunched(LaunchActivatedEventArgs const& e)
{
    Frame rootFrame{ nullptr };
    auto content = Window::Current().Content();
    if (content)
    {
        rootFrame = content.try_as<Frame>();
    }

    // Do not repeat app initialization when the Window already has content,
    // just ensure that the window is active
    if (rootFrame == nullptr)
    {
        Windows::UI::Xaml::Media::SolidColorBrush brush{ Windows::UI::ColorHelper::FromArgb(255, 0, 255, 0) };
        Resources().Insert(winrt::box_value(L"brush"), winrt::box_value(brush));
        // … Other code that VS generates for you …

Chaque FrameworkElement peut avoir un ResourceDictionary

FrameworkElement est une classe de base dont les contrôles héritent, et elle a une propriété Resources. Vous pouvez donc ajouter un dictionnaire de ressources local à n’importe quel FrameworkElement.

Ici, à la fois la page et la bordure ont des dictionnaires de ressources, et elles ont toutes deux une ressource appelée « salutation ». Le TextBlock nommé « textBlock2 » se trouve à l'intérieur de labordure , de sorte que lors de la recherche de ressources, il cherche d’abord dans les ressources de la bordure, puis dans les ressources de la page, et enfin dans les ressources de l'application . Le TextBlock lit « Hola mundo ».

Pour accéder aux ressources de cet élément à partir du code, utilisez la propriété Resources de cet élément. L’accès à un FrameworkElementpour accéder aux ressources dans le code, plutôt qu'en XAML, ne cherchera que dans ce dictionnaire, pas dans ceux des éléments parents.

<Page
    x:Class="MSDNSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Page.Resources>
        <x:String x:Key="greeting">Hello world</x:String>
    </Page.Resources>
    
    <StackPanel>
        <!-- Displays "Hello world" -->
        <TextBlock x:Name="textBlock1" Text="{StaticResource greeting}"/>

        <Border x:Name="border">
            <Border.Resources>
                <x:String x:Key="greeting">Hola mundo</x:String>
            </Border.Resources>
            <!-- Displays "Hola mundo" -->
            <TextBlock x:Name="textBlock2" Text="{StaticResource greeting}"/>
        </Border>

        <!-- Displays "Hola mundo", set in code. -->
        <TextBlock x:Name="textBlock3"/>
    </StackPanel>
</Page>

    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            textBlock3.Text = (string)border.Resources["greeting"];
        }
    }
    MainPage::MainPage()
    {
        InitializeComponent();
        textBlock3().Text(unbox_value<hstring>(border().Resources().TryLookup(winrt::box_value(L"greeting"))));
    }

Dictionnaires de ressources fusionnés

Un dictionnaire de ressources fusionné combine un dictionnaire de ressources en un autre, généralement dans un autre fichier.

Conseil Vous pouvez créer un fichier de dictionnaire de ressources dans Microsoft Visual Studio en utilisant l’option Ajouter > Nouvel élément… > Dictionnaire de ressources dans le menu Projet.

Ici, vous définissez un dictionnaire de ressources dans un fichier XAML distinct appelé Dictionary1.xaml.

<!-- Dictionary1.xaml -->
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MSDNSample">

    <SolidColorBrush x:Key="brush" Color="Red"/>

</ResourceDictionary>

Pour utiliser ce dictionnaire, vous la fusionnez avec le dictionnaire de votre page :

<Page
    x:Class="MSDNSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Page.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Dictionary1.xaml"/>
            </ResourceDictionary.MergedDictionaries>

            <x:String x:Key="greeting">Hello world</x:String>

        </ResourceDictionary>
    </Page.Resources>

    <TextBlock Foreground="{StaticResource brush}" Text="{StaticResource greeting}" VerticalAlignment="Center"/>
</Page>

Voici ce qui se passe dans cet exemple. Dans <Page.Resources>, vous déclarez <ResourceDictionary>. L’infrastructure XAML crée implicitement un dictionnaire de ressources pour vous lorsque vous ajoutez des ressources à <Page.Resources>; Toutefois, dans ce cas, vous ne souhaitez pas seulement un dictionnaire de ressources, vous souhaitez en utiliser un qui contient des dictionnaires fusionnés.

Vous déclarez donc <ResourceDictionary>, puis vous ajoutez des éléments à sa collection <ResourceDictionary.MergedDictionaries>. Chacune de ces entrées prend la forme <ResourceDictionary Source="Dictionary1.xaml"/>. Pour ajouter plusieurs dictionnaires, ajoutez simplement une entrée de <ResourceDictionary Source="Dictionary2.xaml"/> après la première entrée.

Après <ResourceDictionary.MergedDictionaries>…</ResourceDictionary.MergedDictionaries>, vous pouvez éventuellement placer des ressources supplémentaires dans votre dictionnaire principal. Vous utilisez des ressources d’un dictionnaire fusionné à l’instar d’un dictionnaire normal. Dans l’exemple ci-dessus, {StaticResource brush} recherche la ressource dans le dictionnaire enfant/fusionné (Dictionary1.xaml), tandis que {StaticResource greeting} trouve sa ressource dans le dictionnaire de la page principale.

Dans la séquence de recherche de ressources, un dictionnaire MergedDictionaries est vérifié uniquement après une vérification de toutes les autres ressources clés de cette ResourceDictionary. Après avoir recherché ce niveau, la recherche atteint les dictionnaires fusionnés, et chaque élément de MergedDictionaries est coché. Si plusieurs dictionnaires fusionnés existent, ces dictionnaires sont vérifiés dans l'ordre inverse de celui dans lequel ils sont déclarés dans la propriété MergedDictionaries. Dans l’exemple suivant, si Dictionary2.xaml et Dictionary1.xaml ont déclaré la même clé, la clé de Dictionary2.xaml est utilisée en premier, car elle est la dernière dans les MergedDictionaries set.

<Page
    x:Class="MSDNSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Page.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Dictionary1.xaml"/>
                <ResourceDictionary Source="Dictionary2.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Page.Resources>

    <TextBlock Foreground="{StaticResource brush}" Text="greetings!" VerticalAlignment="Center"/>
</Page>

Dans le cadre d’un ResourceDictionary, le dictionnaire est vérifié pour l’unicité des clés. Toutefois, cette portée ne couvre pas différents éléments dans les différents fichiers MergedDictionaries.

Vous pouvez utiliser la combinaison de la séquence de consultation et de l'absence d'application de clé unique dans les étendues de dictionnaires fusionnés pour créer une séquence de valeurs de secours pour les ressources de ResourceDictionary. Par exemple, vous pouvez stocker les préférences utilisateur pour une couleur de pinceau particulière dans le dernier dictionnaire de ressources fusionné dans la séquence, à l’aide d’un dictionnaire de ressources qui se synchronise avec les données d’état et de préférence utilisateur de votre application. Toutefois, si aucune préférence utilisateur n’existe encore, vous pouvez définir cette même chaîne de clé pour une ressource ResourceDictionary dans la ressource initiale MergedDictionaries fichier, et elle peut servir de valeur de secours. N’oubliez pas que toute valeur que vous fournissez dans un dictionnaire de ressources primaire est toujours vérifiée avant la vérification des dictionnaires fusionnés. Par conséquent, si vous souhaitez utiliser la technique de secours, ne définissez pas cette ressource dans un dictionnaire de ressources primaire.

Ressources de thème et dictionnaires de thèmes

Une ThemeResource est similaire à une StaticResource, mais la recherche de ressources est réévaluée lorsque le thème change.

Dans cet exemple, vous définissez l’avant-plan d’un TextBlock sur une valeur du thème actuel.

<TextBlock Text="hello world" Foreground="{ThemeResource FocusVisualWhiteStrokeThemeBrush}" VerticalAlignment="Center"/>

Un dictionnaire de thème est un type spécial de dictionnaire fusionné qui contient les ressources qui varient avec le thème qu’un utilisateur utilise actuellement sur son appareil. Par exemple, le thème « clair » peut utiliser un pinceau de couleur blanche, tandis que le thème « foncé » peut utiliser un pinceau de couleur foncée. Le pinceau modifie la ressource sur laquelle il agit, mais à part cela, la composition d'un contrôle qui utilise le pinceau comme ressource peut rester identique. Pour reproduire le comportement de basculement de thème dans vos propres modèles et styles, au lieu d’utiliser MergedDictionaries en tant que propriété pour fusionner des éléments dans les dictionnaires principaux, utilisez la propriété ThemeDictionaries.

Chaque élément ResourceDictionary dans ThemeDictionaries doit avoir une valeur x :Key. La valeur est une chaîne qui nomme le thème approprié, par exemple « Default », « Dark », « Light » ou « HighContrast ». En règle générale, Dictionary1 et Dictionary2 définissent les ressources qui ont les mêmes noms, mais des valeurs différentes.

Ici, vous utilisez du texte rouge pour le thème clair et du texte bleu pour le thème sombre.

<!-- Dictionary1.xaml -->
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MSDNSample">

    <SolidColorBrush x:Key="brush" Color="Red"/>

</ResourceDictionary>

<!-- Dictionary2.xaml -->
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MSDNSample">

    <SolidColorBrush x:Key="brush" Color="blue"/>

</ResourceDictionary>

Dans cet exemple, vous définissez l’avant-plan d’un TextBlock sur une valeur du thème actuel.

<Page
    x:Class="MSDNSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Page.Resources>
        <ResourceDictionary>
            <ResourceDictionary.ThemeDictionaries>
                <ResourceDictionary Source="Dictionary1.xaml" x:Key="Light"/>
                <ResourceDictionary Source="Dictionary2.xaml" x:Key="Dark"/>
            </ResourceDictionary.ThemeDictionaries>
        </ResourceDictionary>
    </Page.Resources>
    <TextBlock Foreground="{StaticResource brush}" Text="hello world" VerticalAlignment="Center"/>
</Page>

Pour les dictionnaires de thèmes, le dictionnaire actif à utiliser pour les recherches de ressources évolue de manière dynamique, chaque fois que l’extension de balisage ThemeResource est utilisée pour faire référence et que le système détecte une modification de thème. Le comportement de recherche effectué par le système est basé sur le mappage du thème actif au x :Key d’un dictionnaire de thème spécifique.

Il peut être utile d’examiner la façon dont les dictionnaires de thèmes sont structurés dans les ressources de conception XAML par défaut, qui reflètent les modèles qu'utilise Windows Runtime par défaut pour ses contrôles. Ouvrez les fichiers XAML dans \(Program Files)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\<version du SDK>\Generic à l’aide d’un éditeur de texte ou de votre IDE. Notez comment les dictionnaires de thème sont définis en premier dans generic.xaml et comment chaque dictionnaire de thème définit les mêmes clés. Chaque clé de ce type est ensuite référencée par des éléments de composition dans les différents éléments clés qui se trouvent en dehors des dictionnaires de thèmes et définis plus loin dans le code XAML. Il existe également un fichier themeresources.xaml distinct pour la conception qui contient uniquement les ressources de thème et les modèles supplémentaires, et non les modèles de contrôle par défaut. Les zones de thème sont des doublons de ce que vous voyez dans generic.xaml.

Lorsque vous utilisez des outils de conception XAML pour modifier des copies de styles et de modèles, les outils de conception extraient des sections des dictionnaires de ressources de conception XAML et les placent en tant que copies locales d’éléments de dictionnaire XAML qui font partie de votre application et de votre projet.

Pour plus d’informations et pour obtenir la liste des ressources système et spécifiques au thème disponibles pour votre application, consultez ressources de thème XAML.

Comportement de recherche pour les références de ressources XAML

comportement de recherche est le terme qui décrit comment le système de ressources XAML tente de trouver une ressource XAML. La recherche se produit lorsqu’une clé est référencée en tant que référence de ressource XAML à partir d’un emplacement dans le code XAML de l’application. Tout d’abord, le système de ressources a un comportement prévisible pour l’endroit où il vérifie l’existence d’une ressource en fonction de l’étendue. Si une ressource n’est pas trouvée dans l’étendue initiale, l’étendue se développe. Le comportement de recherche se poursuit à travers tous les emplacements et les étendues où une ressource XAML peut potentiellement être définie par une application ou par le système. Si toutes les tentatives de recherche de ressources possibles échouent, une erreur se produit souvent. Il est généralement possible d’éliminer ces erreurs pendant le processus de développement.

Le comportement de recherche pour les références de ressources XAML commence par l’objet où l’utilisation réelle est appliquée et sa propre Resources propriété. Si une ResourceDictionary existe là-bas, cette ResourceDictionary est vérifiée pour un élément ayant la clé demandée. Ce premier niveau de recherche est rarement pertinent, car vous ne définissez généralement pas et référencez ensuite une ressource sur le même objet. En fait, une propriété Resources n'existe souvent pas ici. Vous pouvez utiliser des références de ressources XAML depuis presque n’importe où dans XAML ; vous n’êtes pas limité aux propriétés des sous-classes de FrameworkElement.

La séquence de recherche vérifie ensuite l’objet parent suivant dans l’arborescence d’objets runtime de l’application. Si un FrameworkElement.Resources existe et contient un ResourceDictionary, l’élément de dictionnaire avec la chaîne de clé spécifiée est demandé. Si la ressource est trouvée, la séquence de recherche s’arrête et l’objet est fourni à l’emplacement où la référence a été effectuée. Sinon, le comportement de recherche passe au niveau parent suivant vers la racine de l’arborescence d’objets. La recherche continue de manière récursive vers le haut jusqu’à ce que l’élément racine du code XAML soit atteint, ce qui épuise la recherche de tous les emplacements de ressources immédiats possibles.

Remarque

Il est courant de définir toutes les ressources immédiates au niveau racine d’une page, à la fois pour tirer parti de ce comportement de recherche de ressources et également comme convention de style de balisage XAML.

Si la ressource demandée est introuvable dans les ressources immédiates, l’étape de recherche suivante consiste à vérifier la propriété Application.Resources. Application.Resources est le meilleur endroit pour placer les ressources spécifiques à l’application référencées par plusieurs pages dans la structure de navigation de votre application.

Important

L’ordre des ressources ajoutées à un ResourceDictionary affecte l’ordre dans lequel elles sont appliquées. Le dictionnaire XamlControlsResources remplace de nombreuses clés de ressources par défaut et doit donc être ajouté à Application.Resources tout d’abord afin qu’il ne remplace pas d’autres styles ou ressources personnalisés dans votre application.

Les modèles de contrôle ont un autre emplacement possible dans la recherche de référence : dictionnaires de thèmes. Un dictionnaire de thème est un fichier XAML unique qui a un élément ResourceDictionary comme racine. Le dictionnaire de thème peut être un dictionnaire fusionné à partir de Application.Resources. Le dictionnaire de thème peut potentiellement être le dictionnaire de thème spécifique à un contrôle personnalisé basé sur un modèle.

Enfin, il y a une consultation des ressources par rapport à celles de la plateforme. Les ressources de plateforme incluent les modèles de contrôle définis pour chacun des thèmes de l’interface utilisateur système et qui définissent l’apparence par défaut de tous les contrôles que vous utilisez pour l’interface utilisateur dans une application Windows Runtime. Les ressources de plateforme incluent également un ensemble de ressources nommées liées à l’apparence et aux thèmes à l’échelle du système. Ces ressources sont techniquement un MergedDictionaries élément, et sont donc disponibles pour la recherche à partir de XAML ou du code une fois l’application chargée. Par exemple, les ressources de thème système incluent une ressource nommée « SystemColorWindowTextColor » qui fournit une définition Color pour faire correspondre la couleur du texte de l’application à la couleur de texte d’une fenêtre système qui provient du système d’exploitation et des préférences utilisateur. D’autres styles XAML pour votre application peuvent faire référence à ce style, ou votre code peut obtenir une valeur de recherche de ressource (et la convertir en couleur dans l’exemple de cas).

Pour plus d’informations et pour obtenir la liste des ressources système et spécifiques au thème disponibles pour une application Windows qui utilise XAML, consultez ressources de thème XAML.

Si la clé demandée est toujours introuvable dans l’un de ces emplacements, une erreur/exception d’analyse XAML se produit. Dans certaines circonstances, l’exception d’analyse XAML peut être une exception d’exécution qui n’est pas détectée par une action de compilation de balisage XAML ou par un environnement de conception XAML.

En raison du comportement de recherche hiérarchisé pour les dictionnaires de ressources, vous pouvez définir délibérément plusieurs éléments de ressource qui ont chacune la même valeur de chaîne que la clé, tant que chaque ressource est définie à un niveau différent. En d’autres termes, même si les clés doivent être uniques dans une ResourceDictionarydonnée, l’exigence d’unicité ne s’étend pas à la séquence de comportement de recherche dans son ensemble. Pendant la recherche, seul le premier objet récupéré avec succès est utilisé pour la référence de ressource XAML, puis la recherche s’arrête. Vous pouvez utiliser ce comportement pour demander la même ressource XAML par clé à différentes positions dans le code XAML de votre application, mais récupérer différentes ressources, en fonction de l’étendue à partir de laquelle la référence de ressource XAML a été effectuée et de la façon dont cette recherche particulière se comporte.

Références anticipées dans un ResourceDictionary

Les références de ressource XAML au sein d’un dictionnaire de ressources particulier doivent faire référence à une ressource qui a déjà été définie avec une clé, et cette ressource doit apparaître lexicalement avant la référence de ressource. Les références anticipées ne peuvent pas être résolues par une référence de ressource XAML. Pour cette raison, si vous utilisez des références de ressources XAML à partir d’une autre ressource, vous devez concevoir votre structure de dictionnaire de ressources afin que les ressources utilisées par d’autres ressources soient définies en premier dans un dictionnaire de ressources.

Les ressources définies au niveau de l’application ne peuvent pas faire référence à des ressources immédiates. Cela équivaut à tenter une référence anticipée, car les ressources de l’application sont réellement traitées en premier (au démarrage de l’application et avant le chargement d’un contenu de page de navigation). Toutefois, toute ressource immédiate peut faire référence à une ressource d’application, et il peut s’agir d’une technique utile pour éviter les situations de référence avant.

Les ressources XAML doivent être partageables

Pour qu’un objet existe dans un ResourceDictionary, cet objet doit êtrepartageable .

Étant partageable est requis, car lorsque l’arborescence d’objets d’une application est construite et utilisée au moment de l’exécution, les objets ne peuvent pas exister à plusieurs emplacements de l’arborescence. En interne, le système de ressources crée des copies de valeurs de ressources à utiliser dans le graphique objet de votre application lorsque chaque ressource XAML est demandée.

Un ResourceDictionary et le XAML de Windows Runtime en général prennent en charge ces objets pour une utilisation commune :

Vous pouvez également utiliser des types personnalisés comme ressource partageable si vous suivez les modèles d’implémentation nécessaires. Vous définissez ces classes dans votre code de stockage (ou dans les composants runtime que vous incluez), puis instanciez ces classes en XAML en tant que ressource. Les exemples sont des sources de données d’objet et implémentations IValueConverter pour la liaison de données.

Les types personnalisés doivent avoir un constructeur par défaut, car c’est ce qu’utilise un analyseur XAML pour instancier une classe. Les types personnalisés utilisés comme ressources ne peuvent pas avoir la classe UIElement dans leur héritage, car un UIElement ne peut jamais être partageable (il est toujours conçu pour représenter précisément un élément d'interface utilisateur existant à une position unique dans le graphe objet de votre application d'exécution).

Étendue de l’utilisation de UserControl

Un élément UserControl a une situation particulière pour le comportement de recherche de ressources, car il a les concepts inhérents d’une étendue de définition et d’une étendue d’utilisation. Un UserControl qui fait une référence de ressource XAML à partir de son étendue de définition doit être en mesure de prendre en charge la recherche de cette ressource dans sa propre séquence de recherche d’étendue de définition, autrement dit, il ne peut pas accéder aux ressources d’application. Dans le cadre de l'étendue d'utilisation d'un UserControl, une référence de ressource est traitée comme faisant partie de la séquence de recherche jusqu'à la racine de sa page d'utilisation (tout comme toute autre référence de ressource effectuée à partir d'un objet dans une arborescence d'objets chargée) et peut accéder aux ressources de l'application.

ResourceDictionary et XamlReader.Load

Vous pouvez utiliser un ResourceDictionary comme racine ou comme élément de l'entrée XAML dans la méthode XamlReader.Load. Vous pouvez également inclure des références de ressources XAML dans ce code XAML si toutes ces références sont entièrement autonomes dans le code XAML envoyé pour le chargement. XamlReader.Load analyse le code XAML dans un contexte qui n’est pas conscient d’autres objets ResourceDictionary, pas même Application.Resources. En outre, n’utilisez pas {ThemeResource} depuis le code XAML envoyé à XamlReader.Load.

Utilisation d’un ResourceDictionary à partir du code

La plupart des scénarios d’une ResourceDictionary sont gérés exclusivement en XAML. Vous déclarez le conteneur ResourceDictionary et les ressources au sein d’un fichier XAML ou d’une collection de nœuds XAML dans un fichier de définition d’interface utilisateur. Ensuite, vous utilisez des références de ressources XAML pour demander ces ressources à partir d’autres parties du code XAML. Toutefois, il existe certains scénarios où votre application peut vouloir ajuster le contenu d’un ResourceDictionary à l’aide de code qui s’exécute pendant l’exécution de l’application, ou au moins pour interroger le contenu d’un ResourceDictionary pour voir si une ressource est déjà définie. Ces appels de code sont effectués sur une instance ResourceDictionary. Vous devez donc d’abord en récupérer un , soit un Immédiatement ResourceDictionary quelque part dans l’arborescence d’objets en obtenant FrameworkElement.Resources, ou .

Dans le code C# ou Microsoft Visual Basic, vous pouvez référencer une ressource dans une ResourceDictionary donnée à l’aide de l’indexeur (Item). Une ResourceDictionary est un dictionnaire à clé de chaîne. L’indexeur utilise donc la clé de chaîne au lieu d’un index entier. Dans le code des extensions de composant Visual C++ (C++/CX), utilisez Recherche.

Lorsque vous utilisez du code pour examiner ou modifier unResourceDictionary , le comportement des API telles que recherche ou Élément ne passe pas des ressources immédiates aux ressources d’application ; il s’agit d’un comportement d’analyseur XAML qui se produit uniquement lorsque les pages XAML sont chargées. Au moment de l'exécution, l'étendue des clés est indépendante dans l'instance ResourceDictionary que vous utilisez à ce moment-là. Toutefois, cette étendue s’étend dans MergedDictionaries.

En outre, si vous demandez une clé qui n’existe pas dans leResourceDictionary , il se peut qu’il n’y ait pas d’erreur ; la valeur de retour peut simplement être fournie en tant que null . Toutefois, si vous essayez d’utiliser le null retourné comme valeur, vous pouvez toujours obtenir une erreur. L’erreur provient de l’outil setter de la propriété, et non de votre appel ResourceDictionary. La seule façon d’éviter une erreur est si la propriété a accepté null comme valeur valide. Notez comment ce comportement contraste avec le comportement de recherche XAML au moment de l’analyse XAML ; un échec de résolution de la clé fournie à partir du code XAML au moment de l’analyse entraîne une erreur d’analyse XAML, même dans les cas où la propriété aurait pu accepter null.

Les dictionnaires de ressources fusionnés sont inclus dans l’étendue d’index du dictionnaire de ressources principal qui fait référence au dictionnaire fusionné au moment de l’exécution. En d'autres termes, vous pouvez utiliser Article ou Option de recherche du dictionnaire principal pour trouver les objets effectivement définis dans le dictionnaire fusionné. Dans ce cas, le comportement de recherche ressemble au comportement de recherche XAML lors de l'analyse : s'il y a plusieurs objets dans des dictionnaires fusionnés ayant chacun la même clé, l'objet du dictionnaire ajouté en dernier est renvoyé.

Vous êtes autorisé à ajouter des éléments à un ResourceDictionary existant en appelant Ajouter (C# ou Visual Basic) ou Insérer (C++/CX). Vous pouvez ajouter les éléments aux ressources immédiates ou aux ressources d’application. L’un de ces appels d’API nécessite une clé, qui satisfait à l’exigence que chaque élément d’un ResourceDictionary doit avoir une clé. Toutefois, les éléments que vous ajoutez à un ResourceDictionary au moment de l’exécution ne sont pas pertinents pour les références de ressources XAML. La recherche nécessaire pour les références de ressources XAML se produit lorsque ce code XAML est d’abord analysé lorsque l’application est chargée (ou qu’une modification de thème est détectée). Les ressources ajoutées aux collections au moment de l’exécution n’ont pas été disponibles, et la modification de la ResourceDictionary n’invalide pas une ressource déjà récupérée à partir de celle-ci même si vous modifiez la valeur de cette ressource.

Vous pouvez également supprimer des éléments d’un ResourceDictionary au moment de l’exécution, effectuer des copies de certains ou de tous les éléments ou d’autres opérations. La liste des membres de ResourceDictionary indique quelles API sont disponibles. Notez que, étant donné que ResourceDictionary a une API projetée pour prendre en charge ses interfaces de collection sous-jacentes, vos options d’API diffèrent selon que vous utilisez C# ou Visual Basic ou C++/CX.

ResourceDictionary et localisation

Un XAML ResourceDictionary peut contenir initialement des chaînes à localiser. Dans ce cas, plutôt que dans un ResourceDictionary, stockez ces chaînes en tant que ressources de projet. Supprimez les chaînes du code XAML et donnez plutôt à l’élément propriétaire une valeur de directive x:Uid. Ensuite, définissez une ressource dans un fichier de ressources. Fournissez un nom de ressource sous la forme XUIDValue.PropertyName et une valeur de ressource de la chaîne qui doit être localisée.

Recherche de ressources personnalisée

Pour les scénarios avancés, vous pouvez implémenter une classe qui peut avoir un comportement différent du comportement de recherche de référence de ressource XAML décrit dans cette rubrique. Pour ce faire, vous implémentez la classe CustomXamlResourceLoader, puis vous pouvez accéder à ce comportement à l’aide de l’extension de balisage de CustomResource pour les références de ressources, plutôt que d’utiliser StaticResource ou ThemeResource. La plupart des applications n’ont pas de scénarios qui nécessitent cela. Pour plus d’informations, consultez CustomXamlResourceLoader.