Was ist der Unterschied zwischen StaticResource und DynamicResource in WPF?

474

Wenn Sie Ressourcen wie Pinsel, Vorlagen und Stile in WPF verwenden, können Sie diese entweder als StaticResources angeben

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

oder als DynamicResource

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

Meistens (immer?) Funktioniert nur einer und der andere löst zur Laufzeit eine Ausnahme aus. Aber ich würde gerne wissen warum:

  • Was ist der Hauptunterschied. Wie Gedächtnis- oder Leistungsimplikationen
  • Gibt es in WPF Regeln wie "Pinsel sind immer statisch" und "Vorlagen sind immer dynamisch" usw.?

Ich gehe davon aus, dass die Wahl zwischen Statisch und Dynamisch nicht so willkürlich ist, wie es scheint ... aber ich sehe das Muster nicht.

Isak Savo
quelle
27
Es ist wichtig zu beachten, dass Windows 8 App-Entwickler nicht DyanmicResource als Option haben, sondern nur StaticResource.
Jerry Nixon
2
@ Jerry Nixon Gott sei Dank habe ich die Anzahl der Male verloren, bei denen ich nichts zum Arbeiten bringen konnte, weil ich DynamicResource anstelle von StaticResource verwendet habe oder umgekehrt. Aus Sicht der Programmierer ist dies eine unnötige Komplexität. Eine Analogie sind Variablendefinitionen. Sollte ich explizit angeben müssen, ob sie auf dem Heap oder dem Stack gespeichert sind? Und wenn ich es falsch verstehe, wirft es einen katastrophalen Laufzeitfehler?
Contango
Eine ausführlichere Erläuterung von StaticResource und DynamicResource sowie den jeweiligen Verwendungszweck finden Sie unter msdn.microsoft.com/en-us/library/ms750613%28v=vs.100%29.aspx .
Michael Repucci

Antworten:

466

Eine statische Ressource wird aufgelöst und der Eigenschaft beim Laden der XAML zugewiesen, das erfolgt, bevor die Anwendung tatsächlich ausgeführt wird. Es wird nur einmal zugewiesen und Änderungen am Ressourcenwörterbuch werden ignoriert.

Eine DynamicResource weist der Eigenschaft beim Laden ein Expression-Objekt zu, sucht die Ressource jedoch erst zur Laufzeit, wenn das Expression-Objekt nach dem Wert gefragt wird. Dadurch wird das Nachschlagen der Ressource verzögert, bis sie zur Laufzeit benötigt wird. Ein gutes Beispiel wäre eine Vorwärtsreferenz auf eine Ressource, die später in der XAML definiert wird. Ein weiteres Beispiel ist eine Ressource, die erst zur Laufzeit vorhanden ist. Das Ziel wird aktualisiert, wenn das Quellressourcenwörterbuch geändert wird.

Phil Wright
quelle
4
Was muss sich ändern, bevor ich DynamicResource verwenden muss? Nehmen wir zum Beispiel eine Vorlage: Ich definiere sie einmal, aber dann können natürlich Trigger und andere Dinge den Inhalt der Vorlage ändern, aber die Vorlage ist immer noch dieselbe. Würde StaticResource dies hier tun?
Isak Savo
5
Verwenden Sie StaticResource, wenn die Ressource, an die Sie eine Verbindung herstellen, vor ihrem Verwendungspunkt in der XAML definiert ist und sich während der Lebensdauer der ausgeführten Anwendung nicht ändert. In diesem Fall erzielen Sie mit StaticResource eine bessere Leistung.
Phil Wright
4
Ist die Zwei-Wege-Bindung für beide anwendbar, wenn ja, was wäre der Unterschied in diesem Fall?
WhoIsNinja
11
Der letzte Satz ist wirklich wichtig:It will update the target if the source resource dictionary is changed.
MEMark
4
@IsakSavo Betrachten Sie eine Benutzeroberfläche mit Farbthemen. Mit einer dynamischen Ressource können Sie ein Wörterbuch gegen ein anderes austauschen, und alles, was auf Ressourcen im neuen Wörterbuch verweist, wird automatisch aktualisiert.
Gusdor
119

Ich war auch verwirrt über sie. Siehe dieses Beispiel unten:

<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>

Hier habe ich dynamische Ressourcen für Schaltflächen und Fenster verwendet und sie nirgendwo deklariert. Zur Laufzeit wird das ResourceDictionary der Hierarchie überprüft. Da ich es nicht definiert habe, wird vermutlich die Standardeinstellung verwendet.

Wenn ich den folgenden Code hinzufüge, um auf das Ereignis von Button zu klicken, wird der Hintergrund entsprechend aktualisiert, da DynamicResource verwendet wird.

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

Wenn sie StaticResource verwendet hätten:

  • Die Ressource muss in XAML deklariert werden
  • Und das auch "vorher" werden sie benutzt.

Ich hoffe, ich habe einige Verwirrung beseitigt.

Akshay J.
quelle
31

StaticResource wird bei der Objektkonstruktion aufgelöst.
DynamicResource wird jedes Mal ausgewertet und aufgelöst, wenn die Steuerung die Ressource benötigt.

Afshin
quelle
21
  1. StaticResource verwendet den ersten Wert. DynamicResource verwendet den letzten Wert.
  2. DynamicResource kann für verschachteltes Styling verwendet werden, StaticResource nicht.

Angenommen, Sie haben dieses verschachtelte Stilwörterbuch. LightGreen befindet sich auf der Stammebene, während Pink in einem Raster verschachtelt ist.

<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>

Im Hinblick auf:

<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 rendert die Schaltfläche als LightGreen, den ersten Wert, den sie im Stil gefunden hat. DynamicResource überschreibt die LightGreen-Schaltfläche beim Rendern des Rasters als Pink.

StaticResource StaticResource

DynamicResource DynamicResource

Beachten Sie, dass VS Designer DynamicResource als StaticResource behandelt. Es wird den ersten Wert erhalten. In diesem Fall rendert VS Designer die Schaltfläche als LightGreen, obwohl sie tatsächlich als Pink endet.

StaticResource gibt einen Fehler aus, wenn der Stil auf Stammebene (LightGreen) entfernt wird.

Jeson Martajaya
quelle
13

Was ist der Hauptunterschied. Wie Gedächtnis- oder Leistungsimplikationen

Der Unterschied zwischen statischen und dynamischen Ressourcen entsteht, wenn sich das zugrunde liegende Objekt ändert. Wenn auf Ihren in der Ressourcenauflistung definierten Pinsel im Code zugegriffen und auf eine andere Objektinstanz festgelegt wurde, erkennt Rectangle diese Änderung nicht.

Statische Ressourcen werden einmal durch Referenzieren eines Elements abgerufen und für die Lebensdauer der Ressourcen verwendet. DynamicResources werden bei jeder Verwendung abgerufen.

Der Nachteil dynamischer Ressourcen besteht darin, dass sie die Anwendungsleistung tendenziell verringern.

Gibt es in WPF Regeln wie "Pinsel sind immer statisch" und "Vorlagen sind immer dynamisch" usw.?

Die beste Vorgehensweise besteht darin, statische Ressourcen zu verwenden, es sei denn, es gibt einen bestimmten Grund, warum Sie die Ressource im dahinter stehenden Code dynamisch ändern möchten. Ein weiteres Beispiel für eine Instanz, in der Sie keine dynamischen Ressourcen verwenden möchten, ist die Verwendung der SystemBrushes, SystenFonts und Systemparameter.

CharithJ
quelle
7

Fand alle Antworten nützlich, wollte nur einen weiteren Anwendungsfall hinzufügen.

In einem zusammengesetzten WPF-Szenario kann Ihr Benutzersteuerelement Ressourcen verwenden, die in einem anderen übergeordneten Fenster / Steuerelement (das dieses Benutzersteuerelement hosten wird) definiert sind, indem diese Ressource als DynamicResource bezeichnet wird.

Wie von anderen erwähnt, wird Staticresource zur Kompilierungszeit nachgeschlagen. Benutzersteuerelemente können nicht auf die Ressourcen verweisen, die im Hosting- / übergeordneten Steuerelement definiert sind. In diesem Fall könnte jedoch DynamicResource verwendet werden.

Manish Basantani
quelle
3

Wichtiger Vorteil der dynamischen Ressourcen

Wenn der Start der Anwendung extrem lange dauert, müssen Sie dynamische Ressourcen verwenden, da statische Ressourcen beim Erstellen des Fensters oder der App immer geladen werden, während dynamische Ressourcen bei der ersten Verwendung geladen werden.

Sie werden jedoch keinen Nutzen sehen, wenn Ihre Ressource nicht extrem groß und komplex ist.

Zamoldar
quelle
Erstellt DynamicResources nur einmal ein Leistungsproblem (wird zum ersten Mal verwendet) oder wird es jedes Mal verwendet, wenn das Element verwendet wird?
Morgane
In diesem Fall müssen die meisten verwendeten Felder statische Ressourcen sein, benutzerdefinierte Felder können dynamisch sein, dh für Hauptfenster sind Ressourcen statisch und Dialogfensterressourcen können dynamisch sein
zamoldar
2

Dynamische Ressourcen können nur verwendet werden, wenn sich die festgelegte Eigenschaft auf einem Objekt befindet, das vom Abhängigkeitsobjekt abgeleitet oder eingefroren werden kann, da statische Ressourcen überall verwendet werden können. Sie können das gesamte Steuerelement mithilfe statischer Ressourcen abstrahieren.

Statische Ressourcen werden unter folgenden Umständen verwendet:

  1. Wenn Änderungen der Reaktionsressource zur Laufzeit nicht erforderlich sind.
  2. Wenn Sie eine gute Leistung mit vielen Ressourcen benötigen.
  3. Beim Verweisen auf Ressourcen im selben Wörterbuch.

Dynamische Ressourcen:

  1. Der Wert des Eigenschafts- oder Stilsetzer-Themas ist erst zur Laufzeit bekannt
    • Dies umfasst System-, Anwendungs- und themenbasierte Einstellungen
    • Dies schließt auch Vorwärtsreferenzen ein.
  2. Verweisen auf große Ressourcen, die möglicherweise nicht geladen werden, wenn Seite, Fenster und Benutzersteuerung geladen werden.
  3. Referenzieren von Designstilen in einem benutzerdefinierten Steuerelement.
iaminvinicble
quelle