Quelle est la différence entre StaticResource et DynamicResource dans WPF?

474

Lorsque vous utilisez des ressources telles que des pinceaux, des modèles et des styles dans WPF, ils peuvent être spécifiés en tant que StaticResources

<Rectangle Fill="{StaticResource MyBrush}" />

ou en tant que DynamicResource

<ItemsControl ItemTemplate="{DynamicResource MyItemTemplate}"  />

La plupart du temps (toujours?), Un seul fonctionne et l'autre lève une exception pendant l'exécution. Mais j'aimerais savoir pourquoi:

  • Quelle est la principale différence. Comme la mémoire ou les implications en termes de performances
  • Existe-t-il des règles dans WPF comme "les pinceaux sont toujours statiques" et "les modèles sont toujours dynamiques" etc.?

Je suppose que le choix entre statique et dynamique n'est pas aussi arbitraire qu'il y paraît ... mais je ne vois pas le modèle.

Isak Savo
la source
27
Il est important de noter que les développeurs d'applications Windows 8 n'ont pas DyanmicResource en option, seulement StaticResource.
Jerry Nixon
2
@Jerry Nixon Dieu merci, j'ai perdu le compte du nombre de fois où je n'ai rien pu faire fonctionner parce que j'utilisais DynamicResource au lieu de StaticResource, ou vice-versa. Du point de vue des programmeurs, c'est une complexité inutile. Une analogie est des définitions de variables, devrais-je avoir à spécifier explicitement si elle vit sur le tas ou la pile? Et si je me trompe, cela génère une erreur d'exécution catastrophique?
Contango
Pour une explication plus approfondie de StaticResource et DynamicResource, et quand les utiliser, consultez msdn.microsoft.com/en-us/library/ms750613%28v=vs.100%29.aspx .
Michael Repucci

Réponses:

466

Un StaticResource sera résolu et affecté à la propriété lors du chargement du XAML qui se produit avant que l'application ne soit réellement exécutée. Il ne sera attribué qu'une seule fois et toutes les modifications apportées au dictionnaire de ressources seront ignorées.

Un DynamicResource attribue un objet Expression à la propriété pendant le chargement, mais ne recherche pas réellement la ressource jusqu'au moment de l'exécution lorsque l'objet Expression est invité à saisir la valeur. Cela diffère la recherche de la ressource jusqu'à ce qu'elle soit nécessaire au moment de l'exécution. Un bon exemple serait une référence directe à une ressource définie ultérieurement dans le XAML. Un autre exemple est une ressource qui n'existera même pas jusqu'à l'exécution. Il mettra à jour la cible si le dictionnaire de ressources source est modifié.

Phil Wright
la source
4
Que faut-il changer avant de devoir utiliser DynamicResource? Prenez un modèle par exemple: je le définis une fois, mais bien sûr, les déclencheurs et les éléments peuvent changer le contenu du modèle, mais le modèle est toujours le même. Est-ce que StaticResource ferait ici?
Isak Savo
5
Utilisez StaticResource si la ressource à laquelle vous vous attachez est définie dans le XAML avant son point d'utilisation et ne changera pas pendant la durée de vie de l'application en cours d'exécution. Dans ce cas, vous obtenez de meilleures performances avec StaticResource.
Phil Wright
4
la liaison à deux voies est-elle applicable à ces deux cas?
WhoIsNinja
11
La dernière phrase est vraiment importante:It will update the target if the source resource dictionary is changed.
MEMark
4
@IsakSavo Envisagez une interface utilisateur avec des thèmes de couleurs. Avec une ressource dynamique, vous pouvez échanger un dictionnaire pour un autre et tout ce qui fait référence aux ressources dans le nouveau dictionnaire sera mis à jour automatiquement.
Gusdor
119

J'étais également confus à leur sujet. Voir cet exemple ci-dessous:

<Window x:Class="WpfApplicationWPF.CommandsWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="CommandsWindow" Height="300" Width="300">

    <StackPanel>
        <Button Name="ButtonNew" 
                Click="ButtonNew_Click" 
                Background="{DynamicResource PinkBrush}">NEW</Button>
        <Image Name="ImageNew" 
               Source="pack://application:,,,/images/winter.jpg"></Image>
    </StackPanel>


    <Window.Background>
        <DynamicResource ResourceKey="PinkBrush"></DynamicResource>
    </Window.Background>

</Window>

Ici, j'ai utilisé une ressource dynamique pour le bouton et la fenêtre et je ne l'ai déclarée nulle part. Lors de l'exécution, le ResourceDictionary de la hiérarchie sera vérifié. Puisque je ne l'ai pas défini, je suppose que la valeur par défaut sera utilisée.

Si j'ajoute le code ci-dessous pour cliquer sur l'événement de Button, car ils utilisent DynamicResource, l'arrière-plan sera mis à jour en conséquence.

private void ButtonNew_Click(object sender, RoutedEventArgs e)
{
    this.Resources.Add(  "PinkBrush"
                         ,new SolidColorBrush(SystemColors.DesktopColor)
                       );
}

S'ils avaient utilisé StaticResource:

  • La ressource doit être déclarée en XAML
  • Et cela aussi «avant», ils sont utilisés.

J'espère que j'ai dissipé une certaine confusion.

Akshay J
la source
31

StaticResource sera résolu lors de la construction de l'objet.
DynamicResource sera évalué et résolu chaque fois que le contrôle a besoin de la ressource.

Afshin
la source
21
  1. StaticResource utilise la première valeur. DynamicResource utilise la dernière valeur.
  2. DynamicResource peut être utilisé pour le style imbriqué, StaticResource ne peut pas.

Supposons que vous ayez ce dictionnaire de style imbriqué. LightGreen est au niveau racine tandis que Pink est imbriqué dans une grille.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style TargetType="{x:Type Grid}">
        <Style.Resources>
            <Style TargetType="{x:Type Button}" x:Key="ConflictButton">
                <Setter Property="Background" Value="Pink"/>
            </Style>
        </Style.Resources>
    </Style>
    <Style TargetType="{x:Type Button}" x:Key="ConflictButton">
        <Setter Property="Background" Value="LightGreen"/>
    </Style>
</ResourceDictionary>

En vue:

<Window x:Class="WpfStyleDemo.ConflictingStyleWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ConflictingStyleWindow" Height="100" Width="100">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Styles/ConflictingStyle.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
        <Button Style="{DynamicResource ConflictButton}" Content="Test"/>
    </Grid>
</Window>

StaticResource rendra le bouton en LightGreen, la première valeur trouvée dans le style. DynamicResource remplacera le bouton LightGreen en rose lors du rendu de la grille.

StaticResource StaticResource

DynamicResource DynamicResource

N'oubliez pas que VS Designer traite DynamicResource comme StaticResource. Il obtiendra la première valeur. Dans ce cas, VS Designer rendra le bouton en LightGreen bien qu'il finisse par être rose.

StaticResource générera une erreur lorsque le style de niveau racine (LightGreen) sera supprimé.

Jeson Martajaya
la source
13

Quelle est la principale différence. Comme la mémoire ou les implications en termes de performances

La différence entre les ressources statiques et dynamiques survient lorsque l'objet sous-jacent change. Si votre pinceau défini dans la collection Resources a été accédé dans le code et défini sur une autre instance d'objet, Rectangle ne détectera pas cette modification.

Ressources statiques récupérées une fois en référençant l'élément et utilisées pour la durée de vie des ressources. Alors que DynamicResources récupère chaque fois qu'ils sont utilisés.

L'inconvénient des ressources dynamiques est qu'elles ont tendance à diminuer les performances des applications.

Existe-t-il des règles dans WPF comme "les pinceaux sont toujours statiques" et "les modèles sont toujours dynamiques" etc.?

La meilleure pratique consiste à utiliser les ressources statiques, sauf s'il existe une raison spécifique comme la modification dynamique des ressources dans le code. Un autre exemple d'instance dans laquelle vous voudriez utiliser des résoréductions dynamiques comprend lorsque vous utilisez les SystemBrushes, SystenFonts et les paramètres système.

CharithJ
la source
7

J'ai trouvé toutes les réponses utiles, je voulais juste ajouter un autre cas d'utilisation.

Dans un scénario WPF composite, votre contrôle utilisateur peut utiliser des ressources définies dans toute autre fenêtre / contrôle parent (qui va héberger ce contrôle utilisateur) en faisant référence à cette ressource en tant que DynamicResource.

Comme mentionné par d'autres, Staticresource sera recherché au moment de la compilation. Les contrôles utilisateur ne peuvent pas faire référence aux ressources définies dans l'hébergement / contrôle parent. Cependant, DynamicResource pourrait être utilisé dans ce cas.

Manish Basantani
la source
3

Avantage important des ressources dynamiques

si le démarrage d'une application prend un temps extrêmement long, vous devez utiliser des ressources dynamiques, car les ressources statiques sont toujours chargées lors de la création de la fenêtre ou de l'application, tandis que les ressources dynamiques sont chargées lors de leur première utilisation.

Cependant, vous ne verrez aucun avantage à moins que votre ressource soit extrêmement grande et complexe.

zamoldar
la source
Pour DynamicResources, crée-t-il un problème de performance une seule fois (utilisé pour la première fois) ou à chaque fois que l'élément est utilisé?
Morgane
dans ce cas, la plupart des champs utilisés doivent être des ressources statiques, les champs utilisés personnalisés peuvent être dynamiques, c'est-à-dire que pour les ressources de la fenêtre principale sont statiques et les ressources de la fenêtre de dialogue peuvent être dynamiques
zamoldar
2

Les ressources dynamiques ne peuvent être utilisées que lorsque la propriété en cours de définition se trouve sur un objet dérivé d'un objet de dépendance ou pouvant être congelé alors que des ressources statiques peuvent être utilisées n'importe où. Vous pouvez retirer tout le contrôle à l'aide de ressources statiques.

Les ressources statiques sont utilisées dans les circonstances suivantes:

  1. Lorsque la ressource de réaction change au moment de l'exécution n'est pas requise.
  2. Si vous avez besoin d'une bonne performance avec beaucoup de ressources.
  3. Tout en référençant des ressources dans le même dictionnaire.

Ressources dynamiques:

  1. La valeur de la propriété ou du thème de définition de style n'est pas connue avant l'exécution
    • Cela inclut le système, l'application, les paramètres basés sur le thème
    • Cela inclut également les références directes.
  2. Référencement de grandes ressources qui peuvent ne pas se charger lors du chargement de la page, des fenêtres et du contrôle utilisateur.
  3. Référencement des styles de thème dans un contrôle personnalisé.
iaminvinicble
la source