如果希望在多个项目之间共享资源,可创建资源字典。资源字典只是XAML文档,除了存储希望使用的资源外,不做其他任何事情。

一、创建资源字典

  下面是一个资源字典示例,它包含一个资源:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ImageBrush x:Key="TileBrush" TileMode="Tile"
ViewportUnits="Absolute" Viewport="0 0 32 32"
ImageSource="happyface.jpg" Opacity="0.3"></ImageBrush>
</ResourceDictionary>

  当为应用程序添加资源字典时,务必将Build Action设置为Page(与其他任意XAML文件一样)。这样可保证为了获得最佳性能而将资源字典编译为BAML。不过,将资源字典的Build Action设置为Resource也是非常完美的,这样它会被嵌入到程序集中,但不会被编译。当然,在运行时解析它的速度要稍慢一些。

二、使用资源字典

  为了使用资源字典,需要将其合并到应用程序某些位置的资源集合中。例如,可在特定窗口中执行此操作,但通常将其合并到应用程序的资源集合中。如下所示:

<Application x:Class="Resources.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Menu.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="AppBrushes.xaml"/>
<ResourceDictionary Source="WizardBrushes.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

  上面的标记通过明确创建ResourceDictionary对象进行工作。资源集合总是ResourceDictionary对象,但这只是需要明确指向细节从而可以设置ResourceDictionary.MergedDictionaries属性的一种情况。如果不执行这一步骤,MergedDictionaries属性将为空。

  MergedDictionaries是ResourceDictionary对象的一个集合,可使用该集合提供自己希望使用的资源的集合。这个示例中有两个资源集合:一个在AppBrusheds.xaml资源字典中定义,另一个在WizardBrushes.xaml中定义。

  如果希望添加自己的资源并合并到资源字典中,只需要在MergedDictionaries部分之前或之后放置资源就可以了,如下所示:

<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="AppBrushes.xaml"/>
<ResourceDictionary Source="WizardBrushes.xaml"/>
</ResourceDictionary.MergedDictionaries>
<ImageBrush x:Key="GraphicalBrush1"></ImageBrush>
<ImageBrush x:Key="GraphicalBrush2"></ImageBrush>
</ResourceDictionary>
</Application.Resources>

  使用资源字典的一个原因是为了定义一个或多个可重用的应用程序“皮肤",可将”皮肤“应用到控件上。另一个原因是为了存储需要被本地化的内容。

三、在程序集之间共享资源

  如果希望在多个应用程序之间共享资源字典,可复制并分发包含资源字典的XAML文件。这是最简单的方法,但这样不能对版本进行任何控制。更有条理的方法是将资源字典编译到单独的类库程序集中,并分发组件。

  当共享包含一个或多个资源字典的编译过的程序集时,还需要面对另一个挑战——需要有一种方法提取所希望的资源并在应用程序中使用资源。为此,可使用两种方法。最直观的解决方法是使用代码创建合适的ResourceDictionary对象。例如,如果类库程序集中有名为ReusableDictionary.xaml的资源字典,那么可使用下面的代码手动创建该资源字典:

ResourceDictionary resourceDictionary=new ResourceDictionary();
resourceDictionary.Source=new Uri("ResourceLibrary;component/ReusableDictionary.xaml",UriKind.Relative);

  上面的代码片段使用了在本章前面介绍的pack URI语法。它构造了一个相对URI,该URI指向另一个程序集中名为ReusableDictionary.xaml的编译过的XAML资源。一旦创建ResourceDictionary对象,就可以从集合中手动检索所需的资源了:

cmd.Background=(Brush)resourceDictionary["TileBrush"];

  然而,不必手动指定资源。当加载新的资源字典时,窗口中的所有DynamicResource引用都会被自动重新评估。

  如果不想编写任何代码,还有另一种选择。可使用ComponentResourceKey标记扩展,该标记扩展是专门针对这种情况而设计的。使用ComponentResourceKey为资源创建键名。通过执行这一步骤,告知WPF准备在程序集之间共享资源。

  在继续执行任何操作前,需要确保已经为资源字典提供了正确的名称。为了让这种技巧生效,必须将资源字典放置到generic.xaml文件中,并且必须将该文件放到应用程序文件夹的Themes子文件夹中。generic.xaml文件中的资源被认为是默认主题的一部分,并且它们总是可用的。

  下图显示了合理的文件组织方式,顶部的项目名为ResourceLibray,generic.xaml文件被放在正确的文件夹中。底部的项目名为Resources。该项目有指向ResourceLibrary项目的引用,所以该项目可使用ResourceLibray项目中包含的资源。

  下一步是为存储在ResourceLibray程序集中希望共享的资源创建名。当使用ComponentResourceKey时,需要提供两部分信息:类库程序集中类的引用和描述性的资源ID。类引用是WPF允许的其他程序集共享资源的关键部分。当使用资源时,需要提供相同的类引用和资源ID。

  该类的实际外观并不重要,它不需要包含代码。定义该类型的程序集就是ComponentResourceKey将要从中查找资源的程序集。

  下面是generic.xaml文件的完整标记,它包含了一个单独资源——一个使用不同图形的ImageBrush对象:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ResourceLibrary"
> <ImageBrush
x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type local:CustomResources}, ResourceId=SadTileBrush}"
TileMode="Tile"
ViewportUnits="Absolute" Viewport="0 0 32 32"
ImageSource="ResourceLibrary;component/sadface.jpg" Opacity="0.3">
</ImageBrush> </ResourceDictionary>

  如果眼光敏锐的话,将在该例中发现一个意外细节。ImageSource属性不在被设置为图像名(sadface.jpg),而是使用更复杂的相对URI,明确地指示图像时ResourceLibray组件的一部分。这是必须的步骤,因为将在其他应用程序中使用该资源。如果只是使用图像名,应用程序就会在它自己的资源中查找图像。真正需要的是指定存储图像的组件的相对URI。

  现在已经创建了资源字典,可在另一个应用程序中使用它了。首先,确保已经为类库程序集定义了前缀,如下所示:

<Window x:Class="Resources.ResourceFromLibrary"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:res="clr-namespace:ResourceLibrary;assembly=ResourceLibrary"
Title="ResourceFromLibrary" Height="300" Width="300"
>

  然后可使用包含ComponentResourceKey的DynamicResource(这是合理的,因为ComponentResourceKey是资源名)。在使用资源字典的应用程序中使用ComponentResourceKey,就是在类库中使用的ComponentResourceKey。在此,提供了对同一个类的引用和相同的资源ID。唯一的区别是可能使用不同的XAML名称空间前缀。该例使用res前缀而不是local前缀。从而强调CustomResources类是在另一个程序集中定义的这样一个事实:

<Button Background="{DynamicResource {ComponentResourceKey TypeInTargetAssembly={x:Type res:CustomResources}, ResourceId=SadTileBrush}}"
Padding="5" Margin="5"
FontWeight="Bold" FontSize="14">
A Resource From ResourceLibrary</Button>

  现在该例完成了。但还可以采用一个附加步骤,使资源更容易使用。可定义一个静态属性,让它返回需要使用的正确ComponentResourceKey。通常在组件的类中定义该属性,如下所示:

public class CustomResources
{
public static ComponentResourceKey SadTileBrush
{
get
{
return new ComponentResourceKey(
typeof(CustomResources), "SadTileBrush");
}
}
}

  现在可使用Static标记扩展访问该属性并应用资源,而不必在标记中使用很长的ComponentResourceKey:

<Button Background="{DynamicResource {x:Static res:CustomResources.SadTileBrush}}"
Padding="5" Margin="5"
FontWeight="Bold" FontSize="14">
A Resource From ResourceLibrary
</Button>

  在本质上,这种便捷方法与前面介绍的SystemXxx类使用相同的技术。例如,当检索SystemColors.WindowTextBrushKey时,所接受的也是正确的资源键对象。唯一的区别是,它是私有SystemResourceKey(而不是ComponentResourceKey)的一个实例。这两个类都继承自ResourceKey抽象类。

【WPF学习】第三十五章 资源字典的更多相关文章

  1. 【WPF学习】第十五章 WPF事件

    前两章学习了WPF事件的工作原理,现在分析一下在代码中可以处理的各类事件.尽管每个元素都提供了许多事件,但最重要的事件通常包括以下5类: 生命周期事件:在元素被初始化.加载或卸载时发生这些事件. 鼠标 ...

  2. 【WPF学习】第二十五章 日期控件

    WPF包含两个日期控件:Calender和DatePicker.这两个控件都被设计为允许用户选择日期. Calendar控件显示日期,在与Windows操作系统中看到的日历(例如,当配置系统日期时看到 ...

  3. “全栈2019”Java多线程第三十五章:如何获取线程被等待的时间?

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  4. “全栈2019”Java第三十五章:面向对象

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  5. Gradle 1.12用户指南翻译——第三十五章. Sonar 插件

    本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  6. 风炫安全web安全学习第三十五节课 文件下载和文件读取漏洞

    风炫安全web安全学习第三十五节课 文件下载和文件读取漏洞 0x03 任意文件下载漏洞 一些网站由于业务需求,往往需要提供文件下载功能,但若对用户下载的文件不做限制,则恶意用户就能够下载任意敏感文件, ...

  7. C++ Primer Plus学习:第十五章

    第十五章 友元.异常和其他 友元 友元类 表 0-1 class Tv { public: friend class Remote; } Remote类可以使用Tv的数据成员,Remote类在Tv类后 ...

  8. 【WPF学习】第三十四章 资源基础

    WPF允许在代码中以及在标记中的各个位置定义资源(和特定的控件.窗口一起定义,或在整个应用程序中定义). 资源具有许多重要的优点,如下所述: 高效.可以通过资源定义对象,并在标记中的多个地方使用.这会 ...

  9. 【WPF学习】第二十六章 Application类——应用程序的生命周期

    在WPF中,应用程序会经历简单的生命周期.在应用程序启动后,将立即创建应用程序对象,在应用程序运行时触发各种应用程序事件,你可以选择监视其中的某些事件.最后,当释放应用程序对象时,应用程序将结束. 一 ...

随机推荐

  1. `docker数据持久化volume和bind mounts两种方式

    将数据从宿主机到容器的三种方式: ,volumes:docker管理宿主机文件系统的一部分(/var/lib/docker/volumes)保存数据的最佳方式 ,bind mounts 将宿主机上的任 ...

  2. leetcode.769旋转字符串

    给定两个字符串, A 和 B. A 的旋转操作就是将 A 最左边的字符移动到最右边. 例如, 若 A = 'abcde',在移动一次之后结果就是'bcdea' .如果在若干次旋转操作之后,A 能变成B ...

  3. Spring Boot入门(一)

    Spring Boot入门 一.第一个Spring Boot程序 1.导入springBoot 依赖 <parent> <groupId>org.springframework ...

  4. Django2.2 Cache缓存的设计以及几种方式的 多级或单级缓存处理

    首先照例说明一下缓存的作用以及Django中可以用到的缓存方式: 缓存的作用是用于数据项的再次加载,在设定的时间内可以无压力刷新或者再次访问该数据信息 方式一数据库缓存(Django原生的---有代码 ...

  5. 小小知识点(三十九) 正交频分复用OFDM的基本原理及实现

    引言 符号间干扰(ISI)是无线传输系统设计中需要考虑的因素,采用什么样的处理方法取决于数据传输速率或等效传输带宽来决定 (1)若数据速率低且与信道最大延迟相比符号持续时间较长,那么就可能无需任何均衡 ...

  6. Ant Design Pro中Transfer穿梭框的实际用法(与后端交互)

    Ant Design Pro中Transfer穿梭框的实际用法(与后端交互) 该控件的属性以及属性的作用在ADP的官方文档中都有介绍,但没有讲如何与后端交互,本文旨在讲解该控件与后端的交互. Ant ...

  7. .sarut后缀病毒,勒索病毒

    前两天朋友的电脑中所有的文件后缀名都被改为.sarut 一看就是中了勒索病毒 每个文件夹下都有一个勒索信 查资料后发现这个病毒是STOP病毒的变种 可能是朋友使用windows激活工具了,然后这个病毒 ...

  8. Don’t Repeat Yourself,Repeat Yourself

    Don't Repeat Yourself,Repeat Yourself Don't repeat yourself (DRY, or sometimes do not repeat yoursel ...

  9. C#实现文件Move操作和文件的Copy操作

    文件移动(Move)操作和文件的复制(Copy)是C#程式开发经常遇到的方法,根据传入的源文件地址和目标文件地址参数,实现对文件的操作.实现代码如下: Move操作代码: public static ...

  10. 2、Vue实战-配置篇-npm配置

    引言: 如果刚开始使用 vue 并不了解 nodejs.npm 相关知识可以看我上一篇的实践,快速入门了解实战知识树. Vue实战-入门篇 上篇反思: 1.新的关注点:开发 vue 模板.如何使用本地 ...