静态资源(StaticResource)和动态资源(DynamicResource)

原文: 静态资源(StaticResource)和动态资源(DynamicResource)

静态资源(StaticResource)和动态资源(DynamicResource)

资源能够做为静态资源或动态资源进行引用。这是经过使用 StaticResource 标记扩展或 DynamicResource 标记扩展完成的。css

      StaticResource 经过替换已定义资源的值来为 XAML 属性提供值。html

      DynamicResource 经过将值推迟为对资源的运行时引用来为XAML 属性提供值。动态资源引用强制在每次访问此类资源时都从新进行查找。缓存

      一般来讲,不须要在运行时更改的资源使用静态资源;而须要在运行时更改的资源使用动态资源。动态资源须要使用的系统开销大于静态资源的系统开销。例如如下的例子:性能

   1: <Window x:Class="WPFResource.StaticAndDynamicResource"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     Title="StaticAndDynamicResource" Height="200" Width="300">
   5:     <Window.Resources>
   6:         <SolidColorBrush x:Key="ButtonBrush" Color="Red" />
   7:     </Window.Resources>
   8:     
   9:     <StackPanel>
  10:         <Button Margin="5" Content="Static Resource Button A" Background="{StaticResource ButtonBrush}" />
  11:         <Button Margin="5" Content="Static Resource Button B" Background="{StaticResource ButtonBrush}">
  12:             <Button.Resources>
  13:                 <SolidColorBrush x:Key="ButtonBrush" Color="Yellow" />
  14:             </Button.Resources>
  15:         </Button>
  16:         <Button Margin="5" Content="Change Button Resource" Click="Button_Click" />
  17:         <Button Margin="5" Content="Dynamic Resource Button A" Background="{DynamicResource ButtonBrush}" />
  18:         <Button Margin="5" Content="Dynamic Resource Button B" Background="{DynamicResource ButtonBrush}">
  19:             <Button.Resources>
  20:                 <SolidColorBrush x:Key="ButtonBrush" Color="Yellow" />
  21:             </Button.Resources>
  22:         </Button>
  23:     </StackPanel>
  24: </Window>
   1: private void Button_Click(object sender, RoutedEventArgs e)
   2: {
   3:     SolidColorBrush brush = new SolidColorBrush(Colors.Green);
   4:     this.Resources["ButtonBrush"] = brush;
   5: }

以上的例子在运行时显示以下:ui

StaticAndDynamicResourceA

而点击“Change Button Resource”按钮后,显示的结果为:this

StaticAndDynamicResourceB

从程序执行的结果来看,咱们能够获得以下的结论:spa

  • 静态资源引用是从控件所在的容器开始依次向上查找的,而动态资源的引用是从控件开始向上查找的(即控件的资源覆盖其父容器的同名资源)
  • 更改资源时,动态引用的控件样式发生变化(即"Dynamic Resource Button A"发生变化)

若是要更改"Dynamic Resource Button B"的背景,须要在按钮的事件中添加如下代码(将"Dynamic Resource Button B"的控件的x:Name设置为"btn4")操作系统

   1: SolidColorBrush brushB = new SolidColorBrush(Colors.Blue);
   2: this.btn4.Resources["ButtonBrush"] = brushB;

执行的结果以下:.net

StaticAndDynamicResourceC

 

静态资源引用最适合于如下状况:设计

  • 您的应用程序设计几乎将全部的应用程序资源集中到页或应用程序级别的资源字典中。静态资源引用不会基于运行时行为(例如从新加载页)进行从新求值,所以,根据您的资源和应用程序设计避免大量没必要要的动态资源引用,这样能够提升性能。

  • 您正在设置不在 DependencyObject 或 Freezable 上的属性的值。

  • 您正在建立将编译为 DLL 并打包为应用程序的一部分或在应用程序之间共享的资源字典。

  • 您正在为自定义控件建立一个主题,并定义在主题中使用的资源。对于这种状况,一般不须要动态资源引用查找行为,而须要静态资源引用行为,以使该查找可预测而且独立于该主题。使用动态资源引用时,即便是主题中的引用也会直到运行时才进行求值,而且在应用主题时,某个本地元素有可能会从新定义您的主题试图引用的键,而且本地元素在查找中会位于主题自己以前。若是发生该状况,主题将不会按预期方式运行。

  • 您正在使用资源来设置大量依赖项属性。依赖项属性具备由属性系统启用的有效值缓存功能,所以,若是您为能够在加载时求值的依赖项属性提供值,该依赖项属性将没必要查看从新求值的表达式,而且能够返回最后一个有效值。该方法具备性能优点。

  • 您须要为全部使用者更改基础资源,或者须要经过使用 x:Shared 属性为每一个使用者维护独立的可写实例。

动态资源最适合于如下状况:

  • 资源的值取决于直到运行时才知道的状况。这包括系统资源,或用户可设置的资源。例如,您能够建立引用由 SystemColors、SystemFonts 或 SystemParameters 公开的系统属性的 setter 值。这些值是真正动态的,由于它们最终来自于用户和操做系统的运行时环境。您还可使用能够更改的应用程序级别的主题,在此状况下,页级别的资源访问还必须捕获更改。

  • 您正在为自定义控件建立或引用主题样式。

  • 您但愿在应用程序生存期调整 ResourceDictionary 的内容。

  • 您有一个存在依存关系的复杂资源结构,在这种状况下,可能须要前向引用。静态资源引用不支持前向引用,但动态资源引用支持,由于资源直到运行时才须要进行求值,所以,前向引用不是一个相关概念。

  • 从编译或工做集角度来讲,您引用的资源特别大,而且加载页时可能没法当即使用该资源。静态资源引用始终在加载页时从 XAML 加载;而动态资源引用直到实际使用时才会加载。

  • 您要建立的样式的 setter 值可能来自受主题或其余用户设置影响的其余值。

  • 您正在将资源应用到元素,而在应用程序生存期中可能会在逻辑树中从新设置该元素的父级。更改此父级还可能会更改资源查找范围,所以,若是您但愿基于新范围对从新设置了父级的元素的资源进行从新求值,请始终使用动态资源引用。

不一样类型的资源

一、程序集资源。这种常见于将图片设定到程序集中,作为程序集的资源。

程序集资源在定义时,将文件复制到解决方案-项目所在的目录或其子目录中,并将文件的属性中的Build Action设置为Resource。(注意,WPF不支持项目属性中的资源)

AssemblyResource

 

 

 

 

 

 

而后在XAML文件中使用如Image的Source属性,指定到此文件:

   1: <StackPanel Background="#FFC7DAFF">
   2:     <TextBlock Margin="5" Text="Assembly Resource" />
   3:     <Image Margin="5" Source="Image/Users.png" Width="32" Height="32" />
   4:     <Button Margin="5">
   5:         <Button.Content>
   6:             <StackPanel Orientation="Horizontal">
   7:                 <Image Margin="5" Source="Image/Users.png" Width="32" Height="32" />
   8:                 <TextBlock Text="My Button" VerticalAlignment="Center" />
   9:             </StackPanel>
  10:         </Button.Content>
  11:     </Button>
  12: </StackPanel>

此项目编译后,在Assembly中将封装该图片文件。此种方法适用于较小的资源。

二、对象资源

除刚刚咱们使用的图片作为程序集资源外,前面例子中所使用的资源均是对象资源。系统对于对象资源使用ResouceDictionary这个字典集合处理,其Key对应即x:Key声明的键,Value对应资源。咱们前面使用的都是SolidColorBrush对象,再例如使用字符串及ImageBrush对象作为资源:

   1: <StackPanel Background="#FFE6FDC8">
   2:     <StackPanel.Resources>
   3:         <c:String x:Key="strMessage">My String Value.</c:String>
   4:         <ImageBrush x:Key="imgBrush" ImageSource="Image/Users.png"
   5:                     ViewportUnits="Absolute" Viewport="0 0 32 32"/>
   6:     </StackPanel.Resources>
   7:     <TextBlock Margin="5" Text="Object Resource" />
   8:     <TextBox Margin="5" Text="{StaticResource strMessage}" />
   9:     <Button Margin="5" Height="32" HorizontalContentAlignment="Right" 
  10:             Content="{StaticResource strMessage}" 
  11:             Background="{StaticResource imgBrush}" Width="125" />
  12: </StackPanel>

 

程序执行结果为:

AsmAndObjResource