Vue d'ensemble des ressources
Cette vue d'ensemble explique comment utiliser les ressources de WPF en tant que méthode simple pour réutiliser les objets et valeurs couramment définis. Cette vue d'ensemble met l'accent sur la façon d'utiliser les ressources en XAML. Vous pouvez également créer des ressources et y accéder en utilisant du code, ou en alternant indifféremment entre code et Extensible Application Markup Language (XAML). Pour plus d'informations, consultez Ressources et code.
Cette rubrique comprend les sections suivantes.
- Utilisation des ressources en XAML
- Ressources statiques et dynamiques
- Styles, DataTemplates et clés implicites
- Rubriques connexes
Utilisation des ressources en XAML
L'exemple suivant définit un SolidColorBrush en tant que ressource sur l'élément racine d'une page ressource. L'exemple référence ensuite la ressource et l'utilise pour définir les propriétés de plusieurs éléments enfants, notamment Ellipse, TextBlock et Button.
<Page Name="root"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
>
<Page.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Gold"/>
<Style TargetType="Border" x:Key="PageBackground">
<Setter Property="Background" Value="Blue"/>
</Style>
<Style TargetType="TextBlock" x:Key="TitleText">
<Setter Property="Background" Value="Blue"/>
<Setter Property="DockPanel.Dock" Value="Top"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="Foreground" Value="#4E87D4"/>
<Setter Property="FontFamily" Value="Trebuchet MS"/>
<Setter Property="Margin" Value="0,40,10,10"/>
</Style>
<Style TargetType="TextBlock" x:Key="Label">
<Setter Property="DockPanel.Dock" Value="Right"/>
<Setter Property="FontSize" Value="8"/>
<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>
</Page.Resources>
<StackPanel>
<Border Style="{StaticResource PageBackground}">
<DockPanel>
<TextBlock Style="{StaticResource TitleText}">Title</TextBlock>
<TextBlock Style="{StaticResource Label}">Label</TextBlock>
<TextBlock DockPanel.Dock="Top" HorizontalAlignment="Left" FontSize="36" Foreground="{StaticResource MyBrush}" Text="Text" Margin="20" />
<Button DockPanel.Dock="Top" HorizontalAlignment="Left" Height="30" Background="{StaticResource MyBrush}" Margin="40">Button</Button>
<Ellipse DockPanel.Dock="Top" HorizontalAlignment="Left" Width="100" Height="100" Fill="{StaticResource MyBrush}" Margin="40" />
</DockPanel>
</Border>
</StackPanel>
</Page>
Chaque élément de niveau infrastructure (FrameworkElement ou FrameworkContentElement) possède une propriété Resources, qui est la propriété qui contient les ressources (comme ResourceDictionary) définies par une ressource. Vous pouvez définir les ressources sur n'importe quel élément. Cependant, les ressources sont le plus souvent définies sur l'élément racine, qui est Page dans l'exemple.
Chaque ressource dans un dictionnaire de ressources doit avoir une clé unique. Lorsque vous définissez des ressources dans un balisage, vous affectez la clé unique via l'x:Key, directive. En principe, la clé est une chaîne ; cependant, vous pouvez également la définir selon d'autres types d'objet en utilisant les extensions de balisage appropriées. Les clés qui ne sont pas des chaînes pour les ressources sont utilisées pour certaines fonctionnalités dans WPF, notamment pour les styles, les ressources des composants et le style des données.
Une fois que vous avez défini une ressource, vous pouvez référencer une ressource pour l'utiliser en tant que valeur de propriété à l'aide d'une syntaxe d'extension de balisage de ressource qui spécifie le nom de la clé ; par exemple :
<Button Background="{StaticResource MyBrush}"/>
<Ellipse Fill="{StaticResource MyBrush}"/>
Dans l'exemple précédent, lorsque le chargeur XAML traite la valeur {StaticResource MyBrush} pour la propriété Background sur Button, la logique de recherche de ressource consulte d'abord le dictionnaire des ressources pour l'élément Button. Si Button n'a pas de définition de la clé de ressource MyBrush (ce n'est pas le cas ; sa collection de ressources est vide), la recherche vérifie alors l'élément parent de Button, qui est Page. Ainsi, lorsque vous définissez une ressource sur l'élément racine Page, tous les éléments de l'arborescence logique de Page peuvent y accéder, et vous pouvez réutiliser la même source pour définir la valeur de n'importe quelle propriété qui accepte la Type que la ressource représente. Dans l'exemple précédent, la même ressource MyBrush définit deux propriétés différentes : l'Background d'un Button et le Fill d'un Rectangle.
Ressources statiques et dynamiques
Une ressource peut être référencée soit comme ressource statique soit comme ressource dynamique. Pour ce faire, vous pouvez utiliser StaticResource, extension de balisage ou DynamicResource, extension de balisage. Une extension de balisage est une fonctionnalité de XAML, qui permet de spécifier une référence d'objet en faisant en sorte que l'extension de balisage traite la chaîne d'attribut et retourne l'objet à un chargeur XAML. Pour plus d'informations sur le comportement des extensions de balisage, consultez Extensions de balisage et XAML WPF.
Quand vous utilisez une extension de balisage, vous fournissez en principe un ou plusieurs paramètres qui sont traités par cette extension de balisage particulière, au lieu de les faire évaluer dans le contexte de la propriété qui est définie. L'StaticResource, extension de balisage traite une clé en recherchant la valeur de cette clé dans tous les dictionnaires de ressources disponibles. Cela se produit pendant le chargement, qui est le moment où le processus de chargement doit affecter la valeur de propriété qui prend la référence de la ressource statique. L'DynamicResource, extension de balisage traite plutôt une clé en créant une expression, et cette expression reste sans évaluation jusqu'à l'exécution de l'application, moment où l'expression est évaluée et fournit une valeur.
Lorsque vous référencez une ressource, les considérations suivantes peuvent déterminer si vous utilisez une référence de ressource statique ou une référence de ressource dynamique :
La conception générale de la façon dont vous créez les ressources pour votre application (par page, dans l'application, en XAML libre, dans un assembly ressource seulement).
Fonctionnalité de l'application : la mise à jour des ressources en temps réel fait-elle partie des spécifications de votre application ?
Le comportement de recherche respectif du type référence de cette ressource.
Le type de ressource ou propriété particulière, et le comportement natif de ces types.
Ressources statiques
Les références de la ressource statique fonctionnent au mieux dans les circonstances suivantes :
Votre design d'application concentre l'essentiel de ses ressources sur les dictionnaires de ressources au niveau page ou application. Les références des ressources statiques ne sont pas réévaluées sur la base des comportements au moment de l'exécution, comme le rechargement d'une page, et par conséquent il peut y avoir quelques avantages (en termes de performances) à éviter un grand nombre de références de ressources dynamiques quand elles ne sont pas nécessaires pour vos design d'application et ressource.
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 qui sera compilé dans une DLL, et empaqueté dans le cadre de l'application ou partagé entre applications.
Vous créez un thème pour un contrôle personnalisé, et définissez des ressources qui sont utilisées dans les thèmes. Pour ce cas, vous ne souhaiterez pas le comportement de recherche de référence de ressource dynamique, mais plutôt le comportement de référence de ressource statique de façon que la recherche reste prévisible et autonome dans le thème. Avec une référence de ressource dynamique, même une référence dans un thème est laissée sans évaluation jusqu'au moment de l'exécution, et il est probable que, lorsque le thème sera appliqué, qu'un élément local redéfinisse une clé que votre thème essaie de référencer, et que l'élément local échoue avant le thème lui-même dans la recherche. En ce cas, votre thème n'aura pas le comportement attendu.
Vous utilisez des ressources pour définir de grandes quantités de propriétés de dépendance. Les propriétés de dépendance ont une mise en cache des valeurs effective telle qu'elle est activée par le système de propriétés ; si vous fournissez une valeur pour une propriété de dépendance pouvant être évaluée au moment du chargement, la propriété de dépendance n'a pas besoin de vérifier la présence d'une expression réévaluée et peut retourner la dernière valeur effective. Cette technique peut offrir un gain de performances.
Vous souhaitez modifier la ressource sous-jacente pour tous les consommateurs ou vous souhaitez maintenir séparez des instances accessibles en écriture pour chaque consommateur en utilisant l'attribut x:Shared (voir x:Shared, attribut).
Comportement de recherche de ressource statique
Le processus de recherche vérifie la présence de la clé demandée dans le dictionnaire de ressources défini par l'élément qui paramètre la propriété.
Le processus de recherche parcourt alors l'arborescence logique en amont, jusqu'à l'élément parent et son dictionnaire de ressources. Ce opération se poursuit jusqu'à ce que l'élément racine soit atteint.
Ensuite, les ressources d'application sont vérifiées. Les ressources d'application sont ces ressources du dictionnaire de ressources qui est défini par l'objet Application de votre application WPF.
Les références des ressources statiques à partir du 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 la ressource. Les références vers l'avant ne peuvent pas être résolues avec une référence de ressource statique. Pour cette raison, si vous utilisez des références de ressources statiques, vous devez concevoir la structure de votre dictionnaire des ressources de façon que les ressources soient définies au début ou à proximité du début de chaque dictionnaire de ressources respectif.
La recherche de ressources statiques peut s'étendre aux thèmes, ou dans les ressources système, mais ceci est pris en charge seulement parce que le chargeur XAML diffère la requête. Le différé est nécessaire pour que le thème d'exécution au moment du chargement de la page s'applique correctement à l'application. Cependant, les références de ressources statiques aux clés qui sont connues pour exister seulement dans les thèmes ou en tant que ressources système ne sont pas recommandées. Cela tient au fait que de telles 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 lorsque vous demandez des ressources système ou thème. L'exception est quand 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 indiquées plus haut.
Le comportement d'exception, en cas de référence de ressource statique introuvable, varie. Si la ressource a été différée, l'exception survient alors au moment de l'exécution. Si la ressource n'a pas été différée, l'exception survient alors au moment du chargement.
Ressources dynamiques
Les ressources dynamiques fonctionnent au mieux dans les circonstances suivantes :
La valeur de la ressource dépend des conditions qui ne sont pas connues avant le moment d'exécution. Cela inclut les ressources système, ou les ressources qui sont autrement paramétrables. Par exemple, vous pouvez créer des valeurs d'accesseur Set qui renvoient à des propriétés système, comme exposé par SystemColors, SystemFonts ou SystemParameters. Ces valeurs sont véritablement dynamiques car elles proviennent en fin de compte 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, alors que l'accès aux ressources de niveau page doit également intercepter la modification.
Vous créez ou référencez des styles de thème pour un contrôle personnalisé.
Vous envisagez d'ajuster le contenu d'un ResourceDictionary durant toute la durée de vie d'une application.
Vous avez une structure de ressources complexe avec des interdépendances, ou une référence vers l'avant peut être nécessaire. Les références de ressources statiques ne prennent pas en charge les références vers l'avant, mais les références de ressources dynamiques les prennent en charge car la ressource n'a pas besoin d'être évaluée avant le moment d'exécution, et les références vers l'avant ne sont donc pas un concept pertinent.
Vous référencez une ressource qui est spécialement volumineuse du point de vue d'un jeu de compilation ou de travail, et la ressource pourrait ne pas être utilisée immédiatement lorsque la page est chargée. Les références des ressources statiques sont toujours chargées à partir de XAML lorsque la page est chargée ; cependant, une référence de ressource dynamique n'est chargée que quand elle est réellement utilisée.
Vous créez un style où les valeurs de l'accesseur Set 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 pourraient être à nouveau apparentés dans l'arborescence logique pendant la durée de vie de l'application. Le fait de modifier le parent modifie également potentiellement la portée de la recherche de la ressource, ce qui fait que si vous voulez que la ressource d'un élément à nouveau apparenté soit réévaluée sur la base de la nouvelle portée, veillez à toujours utiliser une référence de ressource dynamique.
Comportement de recherche de ressource dynamique
Le comportement de recherche dynamique pour une référence de ressource dynamique correspond au comportement de recherche dans votre code si vous appelez FindResource ou SetResourceReference.
Le processus de recherche vérifie la présence de la clé demandée dans le dictionnaire de ressources défini par l'élément qui paramètre la propriété.
Le processus de recherche parcourt alors l'arborescence logique en amont, jusqu'à l'élément parent et son dictionnaire de ressources. Ce opération se poursuit jusqu'à ce que l'élément racine soit atteint.
Ensuite, les ressources d'application sont vérifiées. Les ressources d'application sont ces ressources du dictionnaire de ressources qui est défini par l'objet Application de votre application WPF.
Le dictionnaire de ressources de thèmes est consulté, pour le thème actuellement actif. Si le thème change au moment de l'exécution, la valeur est réévaluée.
Les ressources système sont vérifiées.
Comportement d'exception (le cas échéant) varie :
Si une ressource a été demandée par un appel FindResource, et n'a pas été trouvée, une exception est levée.
Si une ressource a été demandée par un appel TryFindResource, et n'a pas été trouvée, aucune une exception n'est levée, mais la valeur retournée est null. Si la propriété en cours de définition n'accepte pas null, il est alors possible qu'une exception plus profonde soit levée (cela dépend de la propriété définie).
Si une ressource a été demandée par une référence de ressource dynamique en XAML, et n'a pas été trouvée, alors le comportement dépend du système de propriétés général, mais le comportement général est similaire à celui du cas où aucune opération de définition de propriété ne s'est produite au niveau où la ressource existe. Par exemple, si vous essayez de définir l'arrière-plan d'un élément bouton en utilisant une ressource qui n'a pas pu être évaluée, aucun jeu de valeurs n'est alors obtenu, mais la valeur effective peut quand même provenir d'autres participants dans le système de propriétés et la priorité des valeurs. Par exemple, la valeur arrière-plan peut quand même provenir d'un style de bouton défini localement, ou du style du thème. Pour les propriétés qui ne sont pas définies par des styles de thème, la valeur effective après un échec d'évaluation de ressource pourrait provenir de la valeur par défaut dans les métadonnées de la propriété.
Restrictions
Références de ressources dynamiques ayant quelques restrictions notables. Au moins l'une des conditions suivantes doit être vraie :
La propriété en cours de définition doit être une propriété sur FrameworkElement ou FrameworkContentElement. Cette propriété doit être stockée par une DependencyProperty.
La référence est pour une valeur contenue dans un Style Setter.
La propriété en cours de définition doit être une propriété sur un Freezable qui est fournie en tant que valeur de la propriété FrameworkElement ou FrameworkContentElement, ou d'une valeur Setter.
Comme la propriété en cours de définition doit être une propriété DependencyProperty ou Freezable, la plupart des modifications apportées à la 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 forcera une autre disposition d'un contrôle si une DependencyProperty change et que cette propriété risque d'affecter la disposition. Cependant, toutes les propriétés qui ont une DynamicResource, extension de balisage comme valeur sont assurées de fournir la valeur de façon à se mettre à jour en temps réel dans l'interface utilisateur. Cette fonctionnalité peut varier en fonction de la propriété, ainsi que selon le type qui possède la propriété, et même la structure logique de votre application.
Styles, DataTemplates et clés implicites
Plus haut, il a été indiqué que tous les éléments contenus dans un ResourceDictionary doivent avoir une clé. Cependant, cela ne signifie pas que toutes les ressources doivent avoir une x:Key explicite. Plusieurs types d'objet prennent en charge une clé implicite lorsqu'ils sont définis en tant que ressource, où la valeur de clé est liée à la valeur d'une autre propriété. C'est ce qu'on appelle une clé implicite, alors qu'un attribut x:Key est une clé explicite. Vous pouvez remplacer toute clé implicite en spécifiant une clé explicite.
Un scénario très important pour les ressources est lorsque vous définissez un Style. En fait, un Style est presque toujours défini en tant qu'entrée dans un dictionnaire de ressources, car les styles sont de manière inhérente destinés à être réutilisés. Pour plus d'informations sur les styles, consultez Application d'un style et création de modèles.
Les styles pour les contrôles peuvent être à la fois créés avec une clé implicite et référencés avec une clé implicite. Les styles de thème qui définissent l'apparence par défaut d'un contrôle se fient à cette clé implicite. La clé implicite du point de vue de sa requête est le Type du contrôle lui-même. La clé implicite du point de vue de la définition de la ressource est le TargetType du style. Par conséquent, si vous créez des thèmes à partir de contrôles personnalisés, en créant des styles qui interagissent avec des styles de thème existant, vous n'avez pas besoin de spécifier un x:Key, directive pour ce Style. Et si vous voulez utiliser les styles à thème, vous n'avez pas besoin de spécifier de style du tout. Par exemple, la définition de style suivante fonctionne, même si la ressource Style ne semble pas avoir une clé :
<Style TargetType="Button">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush>
<GradientStop Offset="0.0" Color="AliceBlue"/>
<GradientStop Offset="1.0" Color="Salmon"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="FontSize" Value="18"/>
</Style>
Ce style a vraiment une clé : la clé implicite typeof(Button). Dans le balisage, vous pouvez spécifier un TargetType directement en tant que nom de type (ou vous pouvez éventuellement utiliser {x:Type...} pour retourner un Type.
Par le biais des mécanismes de style de thème par défaut utilisés par WPF, ce style est appliqué en tant que style d'exécution d'un Button sur la page, même si le Button lui-même ne tente pas de spécifier sa Style propriété ou une référence de ressource spécifique pour le style. Votre style défini dans la page peut être trouvé plus haut dans la séquence de recherche avant le style de dictionnaire de thèmes, en utilisant la même clé que celle du style du dictionnaire de thèmes. Vous pouvez simplement spécifier <Button>Hello</Button> n'importe où dans la page, et le style que vous avez défini avec le TargetType du Button s'appliquerait à ce bouton. Le cas échéant, vous pouvez explicitement définir le style avec la même valeur de type que TargetType par souci de clarté dans votre balisage, mais c'est facultatif.
Les clés implicites pour les styles ne s'appliquent pas à un contrôle si OverridesDefaultStyle est true (à noter également que le OverridesDefaultStyle peut être défini dans le cadre du comportement natif de la classe de contrôle, plutôt qu'explicitement sur une instance du contrôle). De même, afin de prendre en charge les clés implicites pour les scénarios de classe dérivée, le contrôle doit substituer DefaultStyleKey (tous les contrôles existants fournis avec WPF le font). 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 propriété DataType. DataType peut également être spécifié en tant que nom du type plutôt qu'explicitement à l'aide de {x:Type...}. Pour plus d'informations, consultez Vue d'ensemble des modèles de données.
Voir aussi
Tâches
Comment : définir et référencer une ressource
Référence
StaticResource, extension de balisage
DynamicResource, extension de balisage