WPF对象级资源


一、WPF支持程序级资源(也称为二进制资源),和对象级资源。

 

 二、对象级资源简介

  • 简介:对象级资源主要是被应用到各个界面元素中,而每个WPF界面元素都具有一个Resource属性,这个属性继承自FrameworkElement类,其类型为ResourceDictionary(ResourceDictionary是以"键-值"的形式存储资源,通过索引找到资源并应用)。
  • 对象级资源的应用场景主要分为三个:

  ① Application的对象级资源:每新建一个WPF应用,就会自动生成一个App.xaml,这个文件最常用的特性是定义全局资源,这些资源会在整个应用里面被使用。 

1 <Application>
2     <Application.Resources>
3         <TextBlock x:Key="Res1" Text="Hello"/>
4     Application.Resources>
5 Application>

  ② 界面元素的对象级资源:可放在任一控件的Resource属性中,但通常将其放在界面的根元素上,起生效范围是当前界面。

1 <Window>
2    < Window.Resources>
3       <TextBlock x:Key="Res1" Text="Hello"/>
4     Window.Resources>
5 Window>

  ③ 将对象级资源封装成外部资源字典:将对象级资源统一放在资源字典中,在需要使用的地方将其集成,一般都在App.xaml中对资源进行集成。

1 <UserControl>
2    <UserControl.Resources>
3       <ResourceDictionary Source="Res/ControlForDemo.xaml"/>
4    UserControl.Resources>
5 UserControl>

  而资源字典的内容如下

1 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"                    
             xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml" 2 xmlns:local="clr-namespace:DependencyPropertyDemo.Res"> 3   <TextBlock x:Key="Res1" Text="Fighting" x:Shared ="False"/> 4 ResourceDictionary>
  •  x:Shared = "true":对每次请求的资源都使用同个实例。
  •  x:Shared = "false":对每次请求的资源都创建一个新的实例。详细解析:WPF学习之四:x:Shared概述 - 潮儿 - 博客园 (cnblogs.com)
  • 资源字典的编译选项:page或者Resource。

  —— page:可以保证XAML资源文件最终被编译为baml文件,然后可以作为资源插入到.NET框架中,在运行时,框架引擎提取并解析.baml,然后创建一个相应的WPF视觉树或工作流。

  —— Resource:可以嵌入到程序集中,但是不被编译,其解析速度会稍微慢一点。

三、资源字典的集成有两种方式

  • XAML集成外部资源字典
 1 <UserControl>
 2    <UserControl.Resources>
 3       <ResourceDictionary>
 4          <ResourceDictionary.MergedDictionaries>
 5             <ResourceDictionary Source="Res/ButtonStyle.xaml"/>
 6             <ResourceDictionary Source="Res/TextBoxStyle.xaml"/>
 7          ResourceDictionary.MergedDictionaries>
 8        ResourceDictionary>
 9    UserControl.Resources>
10 UserControl>

  ResourceDictionary.MergedDictionaries:该属性是一个ResourceDictionary对象的集合,可以使用这个集合提供多个资源文件。注意:MergedDictionaries下面的每一个ResourceDictionary都必须是独立的,多个ResourceDictionary之间不可以相互引用;ResourceDictionary中定义的key是先进后出的,所以获取到的顺序和定义的顺序是相反的。

  • C#后台代码集成外部资源字典
this.Resources.MergedDictionaries.Add(new ResourceDictionary() 
{ 
    Source = new System.Uri("pack://application:,,,/AddResourceFile;component/Res/TextBoxStyle.xaml") 
});

四、对象级资源的使用

  • 在XAML中使用资源
1 <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
2         <Label Content="{StaticResource Res1}" HorizontalAlignment="Center"/>
3         <Label Content="{DynamicResource Res2}" HorizontalAlignment="Center"/>
4 StackPanel>

  ① StaticResource:仅在程序载入内存时访问该资源一次;

  ② DynamicResource:程序在运行过程中每次使用都会重新访问该资源;

  • 在C#后台代码中使用资源
1 private void Button_Click(object sender, RoutedEventArgs e)
2 {
3     this.label1.Content = this.Resources["Res1"];
4     this.label2.Content = this.FindResource("Res2");
5 }

  ① FindResource:如果找不到请求的资源,会引发异常;

  ② Resources:获取本地的资源,找不到没有异常;

五、对象级资源的检索方式

  •   首先是查找控件自己的Resource属性,若查不到,会沿着逻辑树一级级的查找父控件的Resource属性;
  •   若在父级控件中都查不到,就会去查找Application的Resource属性;
  •   若仍然查找不到,则会异常处理。