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.
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.
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.
StaticResource will be resolved on object construction. DynamicResource will be evaluated and resolved every time control needs the resource.
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.
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.
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.
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.
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.
Success story sharing
It will update the target if the source resource dictionary is changed.