初学WPF的新人有时都会对StaticResource和DynamicResource的概念及应用朦朦胧胧,这里通过一个小例子彻底弄懂这两者的区别及用法。

首先是前台XAML:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<Window x:Class="WpfApplication50.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<SolidColorBrush x:Key="Brush" Color="Red" />
</Window.Resources>
<StackPanel>
<Button Margin="5" Content="Change Resource" Click="Button_Click" />
<Label x:Name="lbl1" Margin="5" Content="Static Resource(Window.Resources)" Background="{StaticResource Brush}" />
<Label x:Name="lbl2" Margin="5" Content="Static Resource(Label.Resources)" Background="{StaticResource Brush}" >
<Label.Resources>
<SolidColorBrush x:Key="Brush" Color="Blue" />
</Label.Resources>
</Label>
<Label x:Name="lbl3" Margin="5" Content="DynamicResource(Window.Resources)" Background="{DynamicResource Brush}" />
<Label x:Name="lbl4" Margin="5" Content="DynamicResource(Label.Resources)" Background="{DynamicResource Brush}" >
<Label.Resources>
<SolidColorBrush x:Key="Brush" Color="Blue" />
</Label.Resources>
</Label>
</StackPanel>
</Window>

后台的代码:

1
2
3
4
5
private void Button_Click(object sender, RoutedEventArgs e)
{
SolidColorBrush brush = new SolidColorBrush(Colors.Yellow);
this.Resources["Brush"] = brush;
}

这段程序很简单的列出了4个Label,两两形成对比,其中lbl1和lbl2使用静态资源,lbl3和lbl4使用动态资源,lbl1和lbl3引用Window.Resources作为源,lbl2和lbl4设置有自身的Resources。

程序的运行效果如下:

可以看到前3个Label都是红色,使用的是Window.Resources。而lbl4却用到了自身的Resources。这至少说明:StaticResource和DynamicResource都是顺逻辑树向上查找父元素的资源字典,直到根节点

点击Button后效果变成:

这时候Window.Resources的Brush资源被改变,但只有lbl3发生了颜色的变化。这也说明了一个问题:使用StaticResource,如果资源改变了,那么不对其产生影响。那么为何lbl4颜色不变呢?接着看。

如果我们把Window.Resources中的<SolidColorBrush x:Key="Brush" Color="Red" />注释掉,看看VS产生了什么报错?

除了lbl4之外,其他3个Label都报错无法解析资源了,通过lbl2,说明了使用StaticResource只会沿着自身的容器向上查找资源,不会查找自身资源。但DynamicResource则不同,他会先查找自身的资源,有则使用,无则沿着逻辑树向上查找。这也就解释了为什么点击按钮之后lbl4的颜色还是不变的原因,因为lbl4使用的是自己的Resource。如果要修改lbl4的资源,那么需要在后台将代码改成:

1
2
3
4
5
private void Button_Click(object sender, RoutedEventArgs e)
{
SolidColorBrush brush = new SolidColorBrush(Colors.Yellow);
this.lbl4.Resources["Brush"] = brush;
}

通过上面的例子可以得出一些简单的结论:

  1. StaticResource从自身的容器开始,向上查找资源,而DynamicResource从自身开始,向上查找资源。也就是说StaticResource不支持向前引用(自身创建引用点后,不能使用自身以后定义的资源)。
  2. StaticResource不会在运行时改变资源,而DynamicResource可以在运行时动态改变资源。
  3. 如果资源在一开始被定义好,并且在运行时不会改变,则使用StaticResource。如果希望支持向后引用或者资源在运行时会动态改变,则使用DynamicResource。
  4. 最后需要提到一点当需要设置的属性不是DependencyObject或Freezable类型的时候,需要用staticResource,而DynamicResource只支持依赖属性,或是Freezable的属性。