WPF Resource

什么叫WPF的资源(Resource)?
资源是保存在可执行文件中的一种不可执行数据。在WPF的资源中,几乎可以包含图像、字符串等所有的任意CLR对象,只要对象有一个默认的构造函数和独立的属性。

也就是说,应用程序中非程序代码的内容,比如点阵图、颜色、字型、动画/影片档以及字符串常量值,可将它们从程序中独立出来,单独包装成"资源(Resource)"。

静态资源(Static Resource),动态资源(Dynamic Resources)。这两者的区别是:静态资源在第一次编译后即确定其对象或值,之后不能对其进行修改。

动态资源则是在运行时决定,当运行过程中真正需要时,才到资源目标中查找其值。因此,我们可以动态地修改它。由于动态资源的运行时才能确定其值,因此效率比静态资源要低。

资源的范围(层级):
WPF提供一个封装和存取资源(resource)的机制,我们可将资源建立在应用程序的不同范围上。WPF中,资源定义的位置决定了该资源的可用范围。资源可以定义在如下范围中:
(1)物件级:此时,资源只能套用在这个Object物件,或套用至该物件的子物件。
(2)文件级:如果将资源定义在Window或Page层级的XAML档中,那么可以套用到这个文件中的所有物件。
(3)应用程序级:如果我们将资源定义在App.xaml 中,那么,就可以将资源套用到应用程序内的任何地方。
(4)字典级:当我们把资源封装成一个资源字典, 定义到一个ResourceDictionary的XAML文件时,就可以在另一个应用程序中重复使用。

每一个框架级元素(FrameworkElement 或者FrameworkContentElement)都有一个资源属性。每一个在资源字典中的资源都有一个唯一不重复的键值(key),在标签中使用x:Key属性来标识它。一般地,键值是一个字符串,但你也可以用合适的扩展标签来设置为其他对象类型。非字符键值资源使用于特定的WPF区域,尤其是风格、组件资源,以及样式数据等。

StaticResources的适用场合:
(1)在资源第一次引用之后无需再修改资源的值。
(2)资源引用不会基于运行时的行为进行重新计算,比如在重新加载Page/Window的时候。
(3)当需要设置的属性不是DependencyObject或Freezable类型的时候,用StaticResource。
(4)当需要将资源编译到dll中,并打包为程序的一部份,或者希望在各应用程序之间共享时,也使用StaticResource。
(5)当需要为一个自定义控件创建一个Theme,并Theme中使用资源,就需要使用StaticResource。因为StaticResource的资源查找行为时可预测的,并且本身包含在Theme中。而对于DynamicResource,即使资源是定义在Theme中,也只能等到运行时确定,导致一些可能意料不到的情况发生。
(6)当需要使用资源设置大量的依赖属性(Dependency Property)的时候。
由于依赖属性具有属性系统提供的值缓存机制,所以,如果能在程序装载时设置依赖属性的值,这样,依赖属性就不需要检查自己的值并返回最后的有效值了。
 
Dynamic Resource一般使用在如下场合:
(1)资源的值依赖一些条件,而该条件直到运行时才能确定。
包括系统资源,或是用户可设置的资源。比如:可以创建引用系统属性诸如SystemColors,SystemFonts来设置值,而这些属性是动态的,它们的值又来自于运行环境和操作系统。
(2)为自定义控件引用或创建Theme Style。
(3)希望在程序运行期间调整资源字典的内容时。
(4)希望资源可以向前引用时(如上面在Canvas中引用innerLgbResource一样)
(5)资源文件很大,希望在运行时才加载。
(6)要创建的Style的值可能来自于其它值,而这些值又依赖于Theme或用户的设置。
(7)当引用资源的元素的父元素有可能在运行期改变,这个时候也需要使用动态资源。因为父元素的改变将导致资源查询的范围。
Dynamic resource的限制条件:属性必须是依赖属性,或是Freezable的。

资源的查询方式
Static Resource的查询
(1)查找使用该资源的元素的Resource字典;
(2)顺着逻辑树向上查找父元素的资源字典,直到根节点;
(3)查找Application资源;
(4)不支持向前引用,即:不能引用在引用点之后才定义的资源。

Dynamic Resource的查询
(1)查找使用该资源的元素的Resource字典;
如果元素定义了一个Style 属性,将查找Style中的资源字典;如果元素定义了一个Template属性,将查找FrameworkTemplate中的资源字典。
(2)顺逻辑树向上查找父元素的资源字典,直到根节点;
(3)查找Application资源;
(4)查找当前激活状态下的Theme资源字典;
(5)查找系统资源。


WPF快速指导1:资源
    本文摘要:
    1:资源应用场景;
    2:静态资源和动态资源;
    3:Application.Current.Resources和Application.Current.Resources.MergedDictionaries
    4:路径


一:资源的应用场景


场景1:格式化界面显示元素
    所谓格式化界面显示元素,就是使用统一的风格来定义软件的每个界面。
    要满足本需求,只需要在App.xaml中如下定义资源

<Application.Resources>
        <Style TargetType="TextBlock" x:Key="TitleText">
            <Setter Property="Background" Value="Blue"/>
            <Setter Property="FontSize" Value="12"/>
        </Style>
        <Style TargetType="TextBlock" x:Key="Label">
            <Setter Property="Background" Value="Blue"/>
            <Setter Property="FontSize" Value="12"/>
        </Style>
</Application.Resources>

同时,在每个页面如下引用资源即可:

    <StackPanel>
        <TextBlock Style="{StaticResource TitleText}">Title</TextBlock>
        <TextBlock Style="{StaticResource Label}">Label</TextBlock>
    </StackPanel>

场景2:动态更新界面风格
    要动态更新界面风格,首先需要定义多种界面风格。假设有Sytle1和Style2两种风格,其中Style1在Style1.xaml中定义:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style TargetType="TextBlock" x:Key="TitleText">
        <Setter Property="Background" Value="Blue"/>
        <Setter Property="FontSize" Value="12"/>
    </Style>
    <Style TargetType="TextBlock" x:Key="Label">
        <Setter Property="Background" Value="Blue"/>
        <Setter Property="FontSize" Value="12"/>
    </Style>
</ResourceDictionary>

Style2在Style2.xaml中定义(假设将Style1中的Blue改为Yellow,12改为24,不再列出)。那么,在页面中,我们如下引用:

    <StackPanel>
        <TextBlock Style="{DynamicResource TitleText}">Title</TextBlock>
        <TextBlock Style="{DynamicResource Label}">Label</TextBlock>
        <Button Click="Button1_Click">Style1</Button>
        <Button Click="Button2_Click">Style2</Button>
    </StackPanel>

同时,后台代码为:

        ResourceDictionary style1;
        ResourceDictionary style2;
        
        private void Button1_Click(object sender, RoutedEventArgs e)
        {
            style1 = new ResourceDictionary();
            style1.Source = new Uri(@"Resouce\Style1.xaml", UriKind.Relative);
            Application.Current.Resources = style1;
        }
        private void Button2_Click(object sender, RoutedEventArgs e)
        {
            style2 = new ResourceDictionary();
            style2.Source = new Uri(@"Resouce\Style2.xaml", UriKind.Relative);
            Application.Current.Resources = style2;
        }

    如此一来,我们便完成动态的界面风格变化。


二:静态资源和动态资源

    在上文的场景二示例中,如果将XAML中的

        <TextBlock Style="{DynamicResource TitleText}">Title</TextBlock>
        <TextBlock Style="{DynamicResource Label}">Label</TextBlock>

    换成

        <TextBlock Style="{StaticResource TitleText}">Title</TextBlock>
        <TextBlock Style="{StaticResource Label}">Label</TextBlock>

    我们会发现界面的风格根本没有得到改变。这里我们引出静态资源和动态资源最重要的一个区别:静态资源不基于运行时行为进行重新求值,而动态资源在运行时加载。
    关于静态资源和动态资源其它区别请查看MSDN。


三:Application.Current.Resources和Application.Current.Resources.MergedDictionaries

    先来看这两个变量的原型:
    Application.Current.Resources的原型是一个ResourceDictionary。
    Application.Current.Resources.MergedDictionaries是一个Collection<ResourceDictionary> 。
    从本质上来讲,这两个变量没有区别,MergedDictionaries是在表现形式上,在运行时扩展系统的资源。
    我们再来看上文中运行时动态改变界面的示例,我们通过动态给Application.Current.Resources赋值,来改变界面风格。
    在实际使用中,必不要这么做。因为不管你是否需要在运行时动态更新部分界面风格,有些资源是肯定不变的。也就是说,一个系统,必定已经存在一个资源文件,即,最好不要在运行时改变Application.Current.Resources。那么,实际要做的,就是动态的增加或者删除Application.Current.Resources.MergedDictionaries就可以了。


四:路径

  第一种:

            imgContent.Source = new BitmapImage(new Uri("Content.jpg", UriKind.Relative)); 
            imgResource.Source = new BitmapImage(new Uri("Resource.jpg", UriKind.Relative));

  第二种:

            imgContent.Source = new BitmapImage(new Uri("pack://application:,,,/Content.jpg")); 
            imgResource.Source = new BitmapImage(new Uri("pack://application:,,,/Resource.jpg"));

  第三种:

            imgContent.Source = new BitmapImage(new Uri("pack://SiteOfOrigin:,,,/Content.jpg")); 

  最后一点需要说说的是路径的问题,关于路径,在WPF中有几种表示方法:

  第一种和第二种都可以访问相对WPF资源路径的Resource和Content资源。第三种方式可以访问运行目录下的Content资源文件以及完全松散的文件。完全松散的文件指那些没有添加到项目中,只是拷贝在程序目录中的文件。

  应用程序根本不知道它的存在。pack://application:,,,/Content.jpg表示当前项目的资源。它是pack://application:,,,/DllName;Component/Content.jpg的简写。将DllName替换成其他程序集,就可以访问其他程序集的资源。

  pack://SiteOfOrigin:,,,/Content.jpg表示从部署位置访问文件。

  pack URI格式是XML文件规范的一部分,具体格式如下 pack://packageURI/partPath。PackageURI实际上是在URI中放一个URI,它是把反斜杠都变成了逗号。packageURI的WPF资源路径可以志向一个XPS文档,例如file : /// c: /Document . xps会被编码为file:...c:,Document.xps。在WPF程序中有两种URI系统是特别处理的:

  siteOfOrigin:/// 编码后siteOfOrigin:,,,

  application:/// 编码后application:,,,

  3个逗号其实是反斜杠编码过来的。


该系列参考:MSDN、《WPF编程》


练习:

1:要统一整个应用程序的风格,应该如何来处理。

2:要对某个特定的页面(Window或Page)上所有的TextBlock统一风格,应该如何处理。

3:静态资源和动态资源的一个区别。

4:Application.Current.Resources和Application.Current.Resources.MergedDictionaries的用处。


一、什么是资源

通常使用 WPF 资源作为重用通常定义的对象和值的简单方法。例如定义一种可以复用的单色的Brush对象,按钮的背景及矩形的填充颜色均使用此Brush:

   1: <Window x:Class="WPFResource.WinBasicResource"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     Title="Basic Resource" Height="200" Width="300">
   5:     <Window.Resources>
   6:         <SolidColorBrush x:Key="myBrush" Color="Gold" />
   7:     </Window.Resources>
   8:     <StackPanel>
   9:         <Button Margin="5" Content="Sample Button" Background="{StaticResource myBrush}" />
  10:         <Rectangle Margin="5" Width="100" Height="100" Fill="{StaticResource myBrush}" />
  11:     </StackPanel>
  12: </Window>

在WPF中资源通常用作“样式”(Style)、样式模板、数据模板等。

二、资源的定义及XAML中引用

资源可以定义在以下几个位置:

  • 应用程序级资源:定义在App.xaml文件中,作为整个应用程序共享的资源存在

在App.xaml文件中定义:

   1: <Application x:Class="WPFResource.App"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     StartupUri="Window1.xaml">
   5:     <Application.Resources>
   6:         <SolidColorBrush Color="Gold" x:Key="myGoldBrush" />
   7:     </Application.Resources>
   8: </Application>

在ApplicationResourceDemo.xaml文件(窗体)中使用App.xaml中定义的Resource

   1: <Window x:Class="WPFResource.ApplicationResourceDemo"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     Title="Application Resource Demo" Height="300" Width="300">
   5:     <StackPanel>
   6:         <Button Margin="5" Background="{StaticResource myGoldBrush}">Sample Button</Button>
   7:     </StackPanel>
   8: </Window>
  • 窗体级资源:定义在Window或Page中,作为一个窗体或页面共享的资源存在
   1: <Window x:Class="WPFResource.WindowResourceDemo"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     Title="WindowResourceDemo" Height="300" Width="300">
   5:     <Window.Resources>
   6:         <SolidColorBrush x:Key="myRedBrush" Color="Red" />
   7:     </Window.Resources>
   8:     <StackPanel>
   9:         <Button Margin="5" Background="{StaticResource myRedBrush}">Sample Button</Button>
  10:     </StackPanel>
  11: </Window>
  • 文件级资源:定义在资源字典的XAML文件中,再引用

在Visual Studio的WPF应用程序项目中,添加“资源字典(Resource Dictionary)”类型的项

15.WPF资源(Resource) - 雅博 - 雅博

在其XAML文件中定义:

   1: <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   2:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   3:     <SolidColorBrush x:Key="myWhiteBrush" Color="White" />
   4: </ResourceDictionary>

在FileResourceDemo.xaml文件(窗体)中,将其注册为窗体级的资源,并引用

   1: <Window x:Class="WPFResource.FileResourceDemo"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     Title="FileResourceDemo" Height="300" Width="300">
   5:     <Window.Resources>
   6:         <ResourceDictionary Source="MyResourceDictionary.xaml" />
   7:     </Window.Resources>
   8:     <StackPanel>
   9:         <Button Margin="5" Background="{StaticResource myWhiteBrush}">Sample Button</Button>
  10:     </StackPanel>
  11: </Window>
  • 对象(控件)级资源:定义在某个ContentControl中,作为其子容器、子控件共享的资源

在Button中定义一个资源,供Button内的Content控件使用

   1: <Window x:Class="WPFResource.ControlResourceDemo"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     Title="ControlResourceDemo" Height="300" Width="300">
   5:     <StackPanel>
   6:         <Button Margin="5">
   7:             <Button.Resources>
   8:                 <SolidColorBrush x:Key="myGreenBrush" Color="Green" />
   9:             </Button.Resources>
  10:             <Button.Content>
  11:                 <TextBlock Text="Sample Text" Background="{StaticResource myGreenBrush}" />
  12:             </Button.Content>
  13:         </Button> 
  14:     </StackPanel>
  15: </Window>

三、XAML解析资源的顺序

在XAML中解析资源按照由引用资源的控件向外层容器依次调用资源。例如在在应用程序级别、窗体级别及对象级别分为定义x:Key相的同资源:

在App.xaml文件中:

   1: <Application x:Class="WPFResource.App"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     StartupUri="MultiResourceReference.xaml">
   5:     <Application.Resources>
   6:         <!-- 应用程序级资源 -->
   7:         <SolidColorBrush Color="Gold" x:Key="myGoldBrush" />
   8:         <SolidColorBrush Color="Blue" x:Key="myBrush" />
   9:     </Application.Resources>
  10: </Application>

在窗体的XAML文件中:

   1: <Window x:Class="WPFResource.MultiResourceReference"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     Title="MultiResourceReference" Height="265" Width="300">
   5:     <Window.Resources>
   6:         <!-- 窗体级资源 -->
   7:         <SolidColorBrush Color="White" x:Key="myWhiteBrush" />
   8:         <SolidColorBrush Color="Green" x:Key="myBrush" />
   9:     </Window.Resources>
  10:     <StackPanel>
  11:         <!-- 使用应用程序级定义的资源 -->
  12:         <Button Margin="5" Content="Sample Button" Background="{StaticResource myGoldBrush}" />
  13:         
  14:         <!-- 使用窗体级定义的资源 -->
  15:         <Button Margin="5" Content="Sample Button" Background="{StaticResource myWhiteBrush}" />
  16:         
  17:         <!-- 窗体级资源的值覆盖应用程序级资源的值 -->
  18:         <Button Margin="5" Content="Sample Button" Background="{StaticResource myBrush}" />
  19:         
  20:         <StackPanel Background="#FF999999">
  21:             <StackPanel.Resources>
  22:                 <!-- 对象级资源 -->
  23:                 <SolidColorBrush Color="Yellow" x:Key="myYellowBrush" />
  24:                 <SolidColorBrush Color="Red" x:Key="myBrush" />
  25:             </StackPanel.Resources>
  26:  
  27:             <!-- 使用应用程序级定义的资源 -->
  28:             <Button Margin="5" Content="Sample Button" Background="{StaticResource myGoldBrush}" />
  29:  
  30:             <!-- 使用窗体级定义的资源 -->
  31:             <Button Margin="5" Content="Sample Button" Background="{StaticResource myWhiteBrush}" />
  32:  
  33:             <!-- 使用对象级定义的资源 -->
  34:             <Button Margin="5" Content="Sample Button" Background="{StaticResource myYellowBrush}" />
  35:  
  36:             <!-- 使用对象级定义的资源覆盖窗体级、应用程序级定义的资源 -->
  37:             <Button Margin="5" Content="Sample Button" Background="{StaticResource myBrush}" />
  38:         </StackPanel>
  39:     </StackPanel>
  40: </Window>

15.WPF资源(Resource) - 雅博 - 雅博

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

资源可以作为静态资源或动态资源进行引用。这是通过使用 StaticResource 标记扩展或 DynamicResource 标记扩展完成的。

通常来说,不需要在运行时更改的资源使用静态资源;而需要在运行时更改的资源使用动态资源。动态资源需要使用的系统开销大于静态资源的系统开销。例如以下的例子:

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

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

15.WPF资源(Resource) - 雅博 - 雅博

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

15.WPF资源(Resource) - 雅博 - 雅博

从程序执行的结果来看,我们可以得到如下的结论:

  • 静态资源引用是从控件所在的容器开始依次向上查找的,而动态资源的引用是从控件开始向上查找的(即控件的资源覆盖其父容器的同名资源)
  • 更改资源时,动态引用的控件样式发生变化(即"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;

执行的结果如下:

15.WPF资源(Resource) - 雅博 - 雅博

静态资源引用最适合于以下情况:

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

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

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

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

  • 您正在使用资源来设置大量依赖项属性。依赖项属性具有由属性系统启用的有效值缓存功能,因此,如果您为可以在加载时求值的依赖项属性提供值,该依赖项属性将不必查看重新求值的表达式,并且可以返回最后一个有效值。该方法具有性能优势。

  • 您需要为所有使用者更改基础资源,或者需要通过使用 x:Shared 属性为每个使用者维护独立的可写实例。

动态资源最适合于以下情况:

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

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

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

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

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

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

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

五、不同类型的资源

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

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

15.WPF资源(Resource) - 雅博 - 雅博

然后在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中将封装该图片文件。此种方法适用于较小的资源。

2、对象资源

除刚刚我们使用的图片做为程序集资源外,前面例子中所使用的资源均是对象资源。系统对于对象资源使用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>

程序执行结果为:

15.WPF资源(Resource) - 雅博 - 雅博



作者:Angelo Lee
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
原文地址:https://www.cnblogs.com/yefengmeander/p/2887675.html