Vue d’ensemble des ressources XAML (WPF .NET)

Une ressource est un objet qui peut être réutilisé à différents endroits dans votre application. Par exemple, les styles et les pinceaux sont des ressources. Cette vue d’ensemble explique comment utiliser des ressources dans XAML (Extensible Application Markup Language). Vous pouvez également créer et accéder aux ressources à l’aide du code.

Remarque

Les ressources XAML décrites dans cet article sont différentes des ressources d’application, qui sont généralement des fichiers ajoutés à une application, telles que du contenu, des données ou des fichiers incorporés.

Important

La documentation du Guide du bureau pour .NET 7 et .NET 6 est en cours de construction.

Utiliser des ressources en XAML

L’exemple suivant définit une SolidColorBrush ressource sur l’élément racine d’une page. L’exemple référence ensuite la ressource et l’utilise pour définir des propriétés de plusieurs éléments enfants, y compris un Ellipse, a TextBlocket un Button.

<Window x:Class="resources.ResExample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ResExample" Height="400" Width="300">
    <Window.Resources>
        <SolidColorBrush x:Key="MyBrush" Color="#05E0E9"/>
        <Style TargetType="Border">
            <Setter Property="Background" Value="#4E1A3D" />
            <Setter Property="BorderThickness" Value="5" />
            <Setter Property="BorderBrush">
                <Setter.Value>
                    <LinearGradientBrush>
                        <GradientStop Offset="0.0" Color="#4E1A3D"/>
                        <GradientStop Offset="1.0" Color="Salmon"/>
                    </LinearGradientBrush>
                </Setter.Value>
            </Setter>
        </Style>
        <Style TargetType="TextBlock" x:Key="TitleText">
            <Setter Property="FontSize" Value="18"/>
            <Setter Property="Foreground" Value="#4E87D4"/>
            <Setter Property="FontFamily" Value="Trebuchet MS"/>
            <Setter Property="Margin" Value="0,10,10,10"/>
        </Style>
        <Style TargetType="TextBlock" x:Key="Label">
            <Setter Property="HorizontalAlignment" Value="Right"/>
            <Setter Property="FontSize" Value="13"/>
            <Setter Property="Foreground" Value="{StaticResource MyBrush}"/>
            <Setter Property="FontFamily" Value="Arial"/>
            <Setter Property="FontWeight" Value="Bold"/>
            <Setter Property="Margin" Value="0,3,10,0"/>
        </Style>
    </Window.Resources>

    <Border>
        <StackPanel>
            <TextBlock Style="{StaticResource TitleText}">Title</TextBlock>
            <TextBlock Style="{StaticResource Label}">Label</TextBlock>
            <TextBlock HorizontalAlignment="Right" FontSize="36" Foreground="{StaticResource MyBrush}" Text="Text" Margin="20" />
            <Button HorizontalAlignment="Left" Height="30" Background="{StaticResource MyBrush}" Margin="40">Button</Button>
            <Ellipse HorizontalAlignment="Center" Width="100" Height="100" Fill="{StaticResource MyBrush}" Margin="10" />
        </StackPanel>
    </Border>

</Window>

Chaque élément au niveau de l’infrastructure (FrameworkElement ou FrameworkContentElement) a une Resources propriété, qui est un ResourceDictionary type qui contient des ressources définies. Vous pouvez définir des ressources sur n’importe quel élément, tel qu’un Button. Toutefois, les ressources sont le plus souvent définies sur l’élément racine, qui se trouve Window dans l’exemple.

Chaque ressource d’un dictionnaire de ressources doit avoir une clé unique. Lorsque vous définissez des ressources dans le balisage, vous affectez cette clé unique à l’aide de la directive x:Key. Cette clé est généralement une chaîne, mais vous pouvez aussi la définir en tant qu’autres types d’objets en utilisant les extensions de balisage appropriées. Les clés non-chaînes pour les ressources sont utilisées par certaines zones de fonctionnalités dans WPF, notamment pour les styles, les ressources de composant et le style de données.

Vous pouvez utiliser une ressource définie avec la syntaxe d’extension de balisage de ressource qui spécifie le nom de clé de la ressource. Par exemple, utilisez la ressource comme valeur d’une propriété sur un autre élément.

<Button Background="{StaticResource MyBrush}"/>
<Ellipse Fill="{StaticResource MyBrush}"/>

Dans l’exemple précédent, lorsque le chargeur XAML traite la valeur {StaticResource MyBrush} de la Background propriété sur Button, la logique de recherche de ressource commence par case activée le dictionnaire de ressources de l’élémentButton. Si Button elle n’a pas de définition de la clé MyBrush de ressource (dans cet exemple, elle n’est pas ; sa collection de ressources est vide), la recherche suivante case activée l’élément parent de Button. Si la ressource n’est pas définie sur le parent, elle continue à case activée l’arborescence logique de l’objet vers le haut jusqu’à ce qu’elle soit trouvée.

Si vous définissez des ressources sur l’élément racine, tous les éléments de l’arborescence logique, tels que le Window ou Page, peuvent y accéder. Et vous pouvez réutiliser la même ressource pour définir la valeur de n’importe quelle propriété qui accepte le même type que la ressource représente. Dans l’exemple précédent, la même MyBrush ressource définit deux propriétés différentes : Button.Background et Ellipse.Fill.

Ressources statiques et dynamiques

Une ressource peut être référencée comme statique ou dynamique. Les références sont créées à l’aide de l’extension staticResource Markup ou de l’extension dynamicResource Markup. Une extension de balisage est une fonctionnalité XAML qui vous permet de spécifier une référence d’objet en ayant l’extension de balisage traiter la chaîne d’attribut et renvoyer l’objet à un chargeur XAML. Pour plus d’informations sur le comportement d’une extension de balisage, consultez Extensions de balisage et XAML WPF.

Lorsque vous utilisez une extension de balisage, vous fournissez généralement un ou plusieurs paramètres sous forme de chaîne qui sont traités par cette extension de balisage particulière. L’extension de balisage StaticResource traite une clé en recherchant la valeur de cette clé dans tous les dictionnaires de ressources disponibles. Le traitement se produit pendant le chargement, c’est-à-dire lorsque le processus de chargement doit affecter la valeur de propriété. L’extension dynamicResource Markup traite à la place une clé en créant une expression et cette expression reste non évaluée tant que l’application n’est pas exécutée, à quel moment l’expression est évaluée pour fournir une valeur.

Quand vous faites référence à une ressource, les points suivants peuvent influer sur votre choix d’utiliser une référence de ressource statique ou à une ressource dynamique :

  • Lorsque vous déterminez la conception globale de la façon dont vous créez les ressources pour votre application (par page, dans l’application, en XAML libre ou dans un assembly resource-only), tenez compte des éléments suivants :

  • Fonctionnalité de l’application. La mise à jour des ressources en temps réel fait-elle partie des exigences de votre application ?

  • Le comportement de recherche respectif de ce type de référence de ressource.

  • Le type de ressource ou de propriété spécifique et le comportement natif de ces types.

Ressources statiques

Les références de ressources statiques conviennent parfaitement dans les conditions suivantes :

  • La conception de votre application concentre la plupart de ses ressources dans des dictionnaires de ressources au niveau de la page ou de l’application.

    Les références de ressources statiques ne sont pas réévaluées en fonction des comportements d’exécution, tels que le rechargement d’une page. Il peut donc y avoir un avantage en matière de performances pour éviter un grand nombre de références de ressources dynamiques lorsqu’elles ne sont pas nécessaires en fonction de la conception de votre ressource et de votre application.

  • Vous définissez la valeur d’une propriété qui n’est pas sur un DependencyObject ou un Freezable.

  • Vous créez un dictionnaire de ressources compilé dans une DLL partagée entre les applications.

  • Vous créez un thème pour un contrôle personnalisé et définissez des ressources utilisées dans les thèmes.

    Dans ce cas, vous ne souhaitez généralement pas le comportement de recherche de référence de ressource dynamique. Au lieu de cela, utilisez le comportement de référence des ressources statiques afin que la recherche soit prévisible et autonome sur le thème. Avec une référence de ressource dynamique, même une référence au sein d’un thème est laissée non évaluée jusqu’au moment de l’exécution. Et il est possible que lorsque le thème est appliqué, un élément local redéfinit une clé que votre thème tente de référencer, et l’élément local tombe avant le thème lui-même dans la recherche. Si cela se produit, votre thème ne se comporte pas comme prévu.

  • Vous utilisez des ressources pour définir un grand nombre de propriétés de dépendance. Les propriétés de dépendance ont une mise en cache de valeur effective activée par le système de propriétés. Par conséquent, si vous fournissez une valeur pour une propriété de dépendance qui peut être évaluée au moment du chargement, la propriété de dépendance n’a pas à case activée pour une expression réévaluée et peut retourner la dernière valeur effective. Cette technique peut s’avérer un gain de performances.

  • Vous souhaitez modifier la ressource sous-jacente pour tous les consommateurs ou vous souhaitez maintenir des instances accessibles en écriture distinctes pour chaque consommateur à l’aide de x:Shared Attribute.

Comportement de la recherche de ressources statiques

Le code suivant décrit le processus de recherche qui se produit automatiquement lorsqu’une ressource statique est référencée par une propriété ou un élément :

  1. Le processus de recherche recherche la clé demandée dans le dictionnaire de ressources qui est spécifié par l’élément définissant la propriété.

  2. Le processus de recherche traverse ensuite l’arborescence logique vers le haut jusqu’à l’élément parent et son dictionnaire de ressources. Ce processus se poursuit jusqu’à ce que l’élément racine soit atteint.

  3. Les ressources d’application sont case activée ed. Les ressources d’application sont ces ressources dans le dictionnaire de ressources définie par l’objet Application de votre application WPF.

Les références de ressources statiques issues d’un dictionnaire de ressources doivent référencer une ressource qui a déjà été définie sur le plan lexical 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 statique. Pour cette raison, concevez votre structure de dictionnaire de ressources de sorte que les ressources soient définies au début ou au début de chaque dictionnaire de ressources respectif.

La recherche de ressources statiques peut s’étendre dans des thèmes ou dans des ressources système, mais cette recherche est prise en charge uniquement parce que le chargeur XAML reporte la requête. Le report est nécessaire afin que le thème d’exécution au moment du chargement de la page s’applique correctement à l’application. Toutefois, les références de ressources statiques aux clés connues pour exister uniquement dans les thèmes ou comme ressources système ne sont pas recommandées, car ces références ne sont pas réévaluées si le thème est modifié par l’utilisateur en temps réel. Une référence de ressource dynamique est plus fiable quand vous demandez des ressources de système ou de thème. L’exception se présente lorsqu’un élément de thème lui-même demande une autre ressource. Ces références doivent être des références de ressources statiques pour les raisons mentionnées précédemment.

Le comportement de l’exception si une référence de ressource statique n’est pas trouvée varie. Si la ressource a été différée, l’exception se produit lors de l’exécution. Si la ressource n’a pas été différée, l’exception se produit au moment du chargement.

Ressources dynamiques

Les ressources dynamiques fonctionnent mieux quand :

  • La valeur de la ressource, y compris les ressources système ou les ressources qui sont autrement définies par l’utilisateur, dépend des conditions qui ne sont pas connues tant que l’exécution n’est pas connue. Par exemple, vous pouvez créer des valeurs setter qui font référence aux propriétés système telles qu’exposées par SystemColors, SystemFontsou SystemParameters. Ces valeurs sont véritablement dynamiques, car elles proviennent de l’environnement d’exécution de l’utilisateur et du système d’exploitation. Vous pouvez également avoir des thèmes de niveau application qui peuvent changer, où l’accès aux ressources de niveau page doit également capturer le changement.

  • Vous créez ou référencez des styles de thème pour un contrôle personnalisé.

  • Vous envisagez d’ajuster le contenu d’une ResourceDictionary durée de vie d’une application.

  • Vous avez une structure de ressources complexe avec des interdépendances, où une référence anticipée peut être nécessaire. Les références de ressources statiques ne prennent pas en charge les références de transfert, mais les références de ressources dynamiques les prennent en charge, car la ressource n’a pas besoin d’être évaluée tant que l’exécution n’est pas nécessaire et que les références de transfert ne sont donc pas un concept pertinent.

  • Vous référencez une ressource volumineuse du point de vue d’un ensemble de compilation ou de travail, et la ressource peut ne pas être utilisée immédiatement lorsque la page se charge. Les références de ressources statiques sont toujours chargées à partir du code XAML lorsque la page se charge. Toutefois, une référence de ressource dynamique ne se charge pas tant qu’elle n’est pas utilisée.

  • Vous créez un style dans lequel les valeurs setter peuvent provenir d’autres valeurs qui sont influencées par des thèmes ou d’autres paramètres utilisateur.

  • Vous appliquez des ressources à des éléments qui peuvent être réparés dans l’arborescence logique pendant la durée de vie de l’application. Le changement de parent peut aussi changer l’étendue de la recherche de ressources, donc si vous souhaitez que la ressource d’un élément réapparenté soit réévaluée en fonction de la nouvelle étendue, utilisez toujours une référence de ressource dynamique.

Comportement de la recherche de ressources dynamiques

Le comportement de recherche de ressource pour une référence de ressource dynamique met en parallèle le comportement de recherche dans votre code si vous appelez FindResource ou SetResourceReference:

  1. La recherche case activée pour la clé demandée dans le dictionnaire de ressources défini par l’élément qui définit la propriété :

  2. La recherche traverse l’arborescence logique vers le haut jusqu’à l’élément parent et son dictionnaire de ressources. Ce processus se poursuit jusqu’à ce que l’élément racine soit atteint.

  3. Les ressources d’application sont case activée ed. Les ressources d’application sont ces ressources dans le dictionnaire de ressources qui sont définies par l’objet Application de votre application WPF.

  4. Le dictionnaire de ressources de thème est case activée ed pour le thème actuellement actif. Si le thème change au moment de l’exécution, la valeur est réévaluée.

  5. Les ressources du système sont recherchées.

Le comportement d’exception (le cas échéant) varie :

  • Si une ressource a été demandée par un FindResource appel et qu’elle n’a pas été trouvée, une exception est levée.

  • Si une ressource a été demandée par un TryFindResource appel et qu’elle n’a pas été trouvée, aucune exception n’est levée et la valeur retournée est null. Si la propriété définie n’accepte nullpas, il est toujours possible qu’une exception plus profonde soit levée, en fonction de la propriété définie.

  • Si une ressource a été demandée par une référence de ressource dynamique en XAML et qu’elle n’a pas été trouvée, le comportement dépend du système de propriétés général. Le comportement général est comme si aucune opération de paramètre de propriété ne s’est produite au niveau où la ressource existe. Par exemple, si vous tentez de définir l’arrière-plan sur un élément de bouton individuel à l’aide d’une ressource qui n’a pas pu être évaluée, aucun résultat de jeu de valeurs, mais la valeur effective peut toujours provenir d’autres participants du système de propriétés et de la priorité des valeurs. Par exemple, la valeur d’arrière-plan peut toujours provenir d’un style de bouton défini localement ou du style de thème. Pour les propriétés qui ne sont pas définies par les styles de thème, la valeur effective après une évaluation de ressource ayant échoué peut provenir de la valeur par défaut dans les métadonnées de propriété.

Restrictions

Les références de ressources dynamiques présentent quelques restrictions notables. Au moins l’une des conditions suivantes doit être remplie :

Étant donné que la propriété définie doit être une DependencyProperty ou Freezable une propriété, la plupart des modifications de propriété peuvent se propager à l’interface utilisateur, car une modification de propriété (la valeur de ressource dynamique modifiée) est reconnue par le système de propriétés. La plupart des contrôles incluent la logique qui force une autre disposition d’un contrôle si une DependencyProperty modification et cette propriété peut affecter la disposition. Toutefois, toutes les propriétés qui ont une extension de balisage DynamicResource, car leur valeur est garantie pour fournir des mises à jour en temps réel dans l’interface utilisateur. Cette fonctionnalité peut toujours varier en fonction de la propriété, et en fonction du type propriétaire de la propriété, ou même de la structure logique de votre application.

Styles, DataTemplates et clés implicites

Bien que tous les éléments d’un élément d’une ResourceDictionary clé aient une clé, cela ne signifie pas que toutes les ressources doivent avoir une clé explicite x:Key. Plusieurs types d’objets prennent en charge une clé implicite lorsqu’elle est définie en tant que ressource, sachant que la valeur d’une clé est liée à la valeur d’une autre propriété. Ce type de clé est appelé clé implicite, et un x:Key attribut est une clé explicite. Vous pouvez remplacer une clé implicite en spécifiant une clé explicite.

Un scénario important pour les ressources est lorsque vous définissez un Style. En fait, un Style élément est presque toujours défini comme une entrée dans un dictionnaire de ressources, car les styles sont intrinsèquement destinés à être réutilisés. Pour plus d’informations sur les styles, consultez Styles et modèles (WPF .NET) .

Des styles de contrôle peuvent être à la fois créés et référencés au moyen d’une clé implicite. Les styles de thème qui définissent l’apparence par défaut d’un contrôle s’appuient sur cette clé implicite. Du point de vue de la demander, la clé implicite est le Type contrôle lui-même. Du point de vue de la définition des ressources, la clé implicite est le TargetType style. Par conséquent, si vous créez des thèmes pour des contrôles personnalisés ou que vous créez des styles qui interagissent avec des styles de thème existants, vous n’avez pas besoin de spécifier une directive x :Key pour cela Style. Et si vous souhaitez utiliser les styles thématiques, vous n’avez pas besoin de spécifier du tout de style. Par exemple, la définition de style suivante fonctionne, même si la Style ressource n’apparaît pas avoir de clé :

<Style TargetType="Button">
    <Setter Property="Background" Value="#4E1A3D" />
    <Setter Property="Foreground" Value="White" />
    <Setter Property="BorderThickness" Value="5" />
    <Setter Property="BorderBrush">
        <Setter.Value>
            <LinearGradientBrush>
                <GradientStop Offset="0.0" Color="#4E1A3D"/>
                <GradientStop Offset="1.0" Color="Salmon"/>
            </LinearGradientBrush>
        </Setter.Value>
    </Setter>
</Style>

Ce style a vraiment une clé : la clé implicite : le System.Windows.Controls.Button type. Dans le balisage, vous pouvez spécifier un TargetType nom de type directement (ou vous pouvez éventuellement utiliser {x :Type...} pour renvoyer un Type.

Par le biais des mécanismes de style de thème par défaut utilisés par WPF, ce style est appliqué comme style d’exécution d’une Button page, même si le Button lui-même n’essaie pas de spécifier sa Style propriété ou une référence de ressource spécifique au style. Votre style défini dans la page est trouvé plus haut dans la séquence de recherche que le style de dictionnaire de thème, en utilisant la même clé que le style de dictionnaire de thème. Vous pouvez simplement spécifier <Button>Hello</Button> n’importe où dans la page, et le style avec lequel TargetTypeButton vous avez défini s’applique à ce bouton. Si vous le souhaitez, vous pouvez toujours clér explicitement le style avec la même valeur de type que TargetType pour la clarté de votre balisage, mais cela est facultatif.

Les clés implicites pour les styles ne s’appliquent pas à un contrôle si c’est le cas OverridesDefaultStyletrue. (Notez également qu’il OverridesDefaultStyle peut être défini dans le cadre du comportement natif de la classe de contrôle, plutôt que explicitement sur une instance du contrôle.) En outre, pour prendre en charge les clés implicites pour les scénarios de classe dérivée, le contrôle doit remplacer DefaultStyleKey (tous les contrôles existants fournis dans le cadre de WPF incluent ce remplacement). Pour plus d’informations sur les styles, les thèmes et la conception de contrôles, consultez Recommandations pour la conception de contrôles auxquels un style peut être appliqué.

DataTemplate a également une clé implicite. La clé implicite d’un DataTemplate est la valeur de DataType propriété. DataType peut également être spécifié comme nom du type plutôt que explicitement à l’aide de {x :Type...}. Pour plus d’informations, consultez Vue d’ensemble des modèles de données.

Voir aussi