最近在做一个WPF的应用,我想在WPF的应用中使用资源字典应该是很常见的事情,由于是初次设计这种程序,对WPF也不是很熟悉,不免会遇上一些问题,当然很多也是一些基础的低级的,比如本文将要介绍的“资源字典将如何在不同程序集之间进行共享”的问题就是一个很基础的技术点。在我的应用程序的设计中将资源字典作为程序集单独设计为类库还不是很必要,但我想我们常见的系统中这么做应该是很不错的选择吧,所以,我就很想明白此时我应该怎么做,可是在我从网上查找相关资料时发现这方面的介绍不是很多,而且,介绍的也不够清楚,大多还是很笼统,给的例子也都千篇一律——以我的智商还不能做到被一点即通。于是便查阅了一些书籍,终于在《WPF编程宝典——C# 2010版》中找的较详细的介绍,所以,我想把我学到的做个总结记录下来以供大家参考和我以后的查看。
我想我这里即将介绍的这个知识对于初始WPF的人应该还是能有帮助的吧,希望如此。至少,我看了书里的介绍还是觉得还是很清楚的,如果我这里的介绍给到家带来困扰了,还希望能够不客气的指出,另外,也可以去看下书中原文(原文写的还是很清楚,条理也很清晰的)。关于资源字典、如何创建和使用资源字典是很简单的,随便查一下资料就能明白了,这里我们还是先关注一下它在不同程序集间的共享。
如果只是在不同窗体或控件之间共享倒是简单了,关键是怎么能在不同程序集间共享。尤其是大点的项目,我们很有可能需要单独创建一个资源字典的程序集作为资源类库进行共享。那如果是这种情况我们该怎么办呢?除了直接拷贝资源字典的XAML文件并分发以外(当然这不是什么好的选择)我们还有两个办法:1、使用代码创建合适的 ResourceDictionary 对象(这种做法比较直观);2、使用 ComponentResourceKey 标记扩展,该标记扩展也是专门为此设计的。
一、使用代码创建 ResourceDictionary 对象:
1、假设资源字典专用类库为 ResourceDictionaryLibrary ,要使用其中的一个资源字典为 ButtonBackgroundDic.xaml 的资源字典,可以使用下面的代码进行访问:
ResourceDictionary resDictionary = new ResourceDictionary(); resDictionary.Source = new Uri("ResourceDictionaryLibrary;component/ButtonBackgroundDic.xaml",UriKind.Relative);
2、在使用时,我们就可以通过Key来手动检索所需的资源了,如下代码所示(其中 BtnBackgound_SkyBlue 是我要用的资源的 Key ;btn 是我使用该资源的一个 Button ):
this.btn.Background = (Brush)resourceDic["BtnBackgound_SkyBlue"];
注:
在上面代码中使用了 pack URI 语法,这里仅作简单介绍,具体语法讲解请查阅相关资料:
语法格式为 ResourceName(相对URI)或 pack://application:,,,/ResourceName(绝对URI),两种写法是等效的;但对于检索嵌入到其他资源库中的资源时语法格式为 AssemblyName;component/ResourceName(相对URI)或 pack://application:,,,/AssemblyName;component/ResourceName(绝对URI)(如在上述例子中使用的格式为:”AssemblyName;component/ResourceName“)。
二、使用 ComponentResourceKey 标记扩展:
如果不想写任何代码,则可以使用 ComponentResourceKey 标记扩展。
1、使用 ComponentResourceKey 为资源创建键名,这可起到通知 WPF 我们将在程序集之间共享资源。
2、使用这种方式时,我们务必将资源字典整合到 Generic.xaml 文件中,并且必须将该文件位于 Themes 文件夹中。
目录结构大概是这样的:ResourceDictionaryLibrary/Themes/Generic.xaml
更合了资源字典的 Generic.xaml 文件大致是这样的:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:ResourceDictionaryLibrary"> <ResourceDictionary.MergedDictionaries> <!--该资源是要使用在其他程序集中,因此使用下面的 pack URI 语法在其他程序访问该资源时才能正常运行。如果直接指定资源文件名称,则程序将会在自己的资源中查找。--> <ResourceDictionary Source="ResourceDictionaryLibrary;component/ButtonBackgroundDic.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary>
3、为需要共享的资源创建键名。
使用 ComponentResourceKey 时,需要提供两部分信息:类库程序集中类的引用和描述性的资源ID。类引用是共享资源的关键。当在使用时,需要提供相同的类引用和资源ID。
该类无所谓定义为什么名,也可以没有任何代码。但是,需要将该类定义到 ComponentResourceKey 将要从中查找资源的程序集(如我们单独创建的资源字典的程序集),比如我将该类定义成如下样子:
public class CustomResources { }
4、使用上面的 CustomResources 类和资源ID创建键名:
x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type local:CustomResources},ResourceId=BtnBackgound_SkyBlue}"
5、在其他应用程序中的使用:
xmlns:res="clr-namespace:ResourceDictionaryLibrary;assembly=ResourceDictionaryLibrary"
<Button Name="btn" Background="{DynamicResource {ComponentResourceKey TypeInTargetAssembly={x:Type res:CustomResources},ResourceId=BtnBackgound_SkyBlue}}"/>
注:使用 ComponentResourceKey 时,必须使用动态资源,而不能使用静态资源。
public class CustomResources {
/// <summary>
/// 属性名不必与 ComponentResourceKey 的 resourceId 相同
/// </summary>
public static ComponentResourceKey BtnBackgound_SkyBlue { get { return new ComponentResourceKey(typeof(CustomResources), "BtnBackgound_SkyBlue"); } } }
此时,可以使用 Static 标记扩展访问该属性了并应用资源了,代码如下:
<Button Name="btn" Background="{DynamicResource {x:Static res:CustomResources.BtnBackgound_SkyBlue}}"/>