ChatGPT解决这个技术问题 Extra ChatGPT

What's the difference between StaticResource and DynamicResource in WPF?

When using resources such as brushes, templates and styles in WPF, they can be specified either as StaticResources

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

or as a DynamicResource

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

Most of the times (always?), only one works and the other will throw exception during runtime. But I'd like to know why:

What is the main difference. Like memory or performance implications

Are there rules in WPF like "brushes are always static" and "templates are always dynamic" etc.?

I assume the choice between Static vs Dynamic isn't as arbitrary as it seems... but I fail to see the pattern.

It is important to note that Windows 8 App developers do not have DyanmicResource as an option, only StaticResource.
@Jerry Nixon Thank God for that, I've lost count of the number of times I couldn't get anything to work because I was using DynamicResource instead of StaticResource, or vice-versa. From the programmers point of view, this is unnecessary complexity. An analogy is variable definitions, should I have to explicitly specify whether it lives on the heap or the stack? And if I get it wrong it throws a catastrophic runtime error?
For a more thorough explanation of StaticResource and DynamicResource, and when to use each, see msdn.microsoft.com/en-us/library/ms750613%28v=vs.100%29.aspx.

M
Matt

A StaticResource will be resolved and assigned to the property during the loading of the XAML which occurs before the application is actually run. It will only be assigned once and any changes to resource dictionary ignored.

A DynamicResource assigns an Expression object to the property during loading but does not actually lookup the resource until runtime when the Expression object is asked for the value. This defers looking up the resource until it is needed at runtime. A good example would be a forward reference to a resource defined later on in the XAML. Another example is a resource that will not even exist until runtime. It will update the target if the source resource dictionary is changed.


What has to change before I need to use DynamicResource? Take a template for instance: i define it once but then of course triggers and stuff can change the content of the template but the template is still the same. Would StaticResource do here?
Use StaticResource if the resource you are attaching to is defined in the XAML before its point of use and is not going to change for the lifetime of the application running. In that case you get better performance with StaticResource.
is twoWay binding applicable on both of these, if yes what would be the difference in that case?
The last sentence is really important: It will update the target if the source resource dictionary is changed.
@IsakSavo Consider a UI with colour themes, With a dynamic resource, you can swap one dictionary for another and anything referencing resources in the new dictionary will update automatically.
G
Gennady Vanin Геннадий Ванин

I was also confused about them. See this example below:

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

Here I have used dynamic resource for button and window and have not declared it anywhere.Upon runtime, the ResourceDictionary of the hierarchy will be checked.Since I have not defined it, I guess the default will be used.

If I add the code below to click event of Button, since they use DynamicResource, the background will be updated accordingly.

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

If they had used StaticResource:

The resource has to be declared in XAML

And that too "before" they are used.

Hope I cleared some confusion.


A
Afshin

StaticResource will be resolved on object construction. DynamicResource will be evaluated and resolved every time control needs the resource.


J
Jeson Martajaya

StaticResource uses first value. DynamicResource uses last value. DynamicResource can be used for nested styling, StaticResource cannot.

Suppose you have this nested Style dictionary. LightGreen is at the root level while Pink is nested inside a Grid.

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

In view:

<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 will render the button as LightGreen, the first value it found in the style. DynamicResource will override the LightGreen button as Pink as it renders the Grid.

https://i.stack.imgur.com/dYc0V.png

https://i.stack.imgur.com/MLGoJ.png

Keep in mind that VS Designer treats DynamicResource as StaticResource. It will get first value. In this case, VS Designer will render the button as LightGreen although it actually ends up as Pink.

StaticResource will throw an error when the root-level style (LightGreen) is removed.


Still confusing how the LightGreen is found first in the resource dictionary, cause the Pink is declared first (as the one more above). I guess when the xaml looks for the style it matches first the "not-nested" one. A short explanation would be helpful though.
C
CharithJ

What is the main difference. Like memory or performance implications

The difference between static and dynamic resources comes when the underlying object changes. If your Brush defined in the Resources collection were accessed in code and set to a different object instance, Rectangle will not detect this change.

Static Resources retrieved once by referencing element and used for the lifetime of the resources. Whereas, DynamicResources retrieve every time they are used.

The downside of Dynamic resources is that they tend to decrease application performance.

Are there rules in WPF like "brushes are always static" and "templates are always dynamic" etc.?

The best practice is to use Static Resources unless there is a specific reason like you want to change resource in the code behind dynamically. Another example of instance in which you would want t to use dynamic resoruces include when you use the SystemBrushes, SystenFonts and System Parameters.


M
Manish Basantani

Found all answers useful, just wanted to add one more use case.

In a composite WPF scenario, your user control can make use of resources defined in any other parent window/control (that is going to host this user control) by referring to that resource as DynamicResource.

As mentioned by others, Staticresource will be looked up at compile time. User controls can not refer to those resources which are defined in hosting/parent control. Though, DynamicResource could be used in this case.


"Staticresource will be looked up at compile time.". I don't think so. "compile time" would mean "at the time the app is built". See Static resource lookup behavior. Static resource is looked up when the xaml is first loaded. That happens at run time. The difference between static and dynamic is that static lookup only happens ONCE (and follows simpler lookup rules). Consider "Static resource lookup can extend into themes or into system resources"".
Ahh, I was thinking about how a page uses your control, not what your control can do within its resource dictionary. I see your point - it is implied by "Static resource references from within a resource dictionary must reference a resource that has already been defined lexically before the resource reference." - which I see requires being resolvable at compile time.
z
zamoldar

Important benefit of the dynamic resources

if application startup takes extremely long time, you must use dynamic resources, because static resources are always loaded when the window or app is created, while dynamic resources are loaded when they’re first used.

However, you won’t see any benefit unless your resource is extremely large and complex.


For DynamicResources, is it creating a performance issue only once (used for the first time) or is it each time the element is used ?
in this case most used fields must be static resource, custom used fields can be dynamic, ie for mainwindow resources are static and dialog window resource can be dynamic
In some situations, can't you work around this limitation, by writing code that adds to resource dictionary before the second page's XAML is loaded?
W
Wolfgang

Dynamic resources can only be used when property being set is on object which is derived from dependency object or freezable where as static resources can be used anywhere. You can abstract away entire control using static resources.

Static resources are used under following circumstances:

When reaction resource changes at runtime is not required. If you need a good performance with lots of resources. While referencing resources within the same dictionary.

Dynamic resources:

Value of property or style setter theme is not known until runtime This include system, aplication, theme based settings This also includes forward references. Referencing large resources that may not load when page, windows, usercontrol loads. Referencing theme styles in a custom control.