来自《深入浅出WPF》(刘铁猛)读书笔记
WPF不但支持程序级的传统资源,同时还推出独具特色的对象级资源,每个界面元素都可以携带自己的资源并可被自己的子级元素共享。
WPF程序中数据就分为4个等级存储:数据库里的数据相当于存放在仓库里,资源文件里的数据相当于放在旅行箱里,WPF对象资源里的数据相当于放在随声携带的背包里,变量中的数据相当于拿在手上。
每个WPF的界面元素都具有一个名为Resources的属性,这个属性继承自FrameworkElement类,其类型为ResourceDictionary。ReousceDictionary能够以“键-值”对的形式存储资源,当需要使用某个资源时,使用“键-值”对可以索引到资源对象。在保存资源时,ResourceDictionary视资源对象为Object类型,所以在使用资源时要对资源对象进行类型转换,XAML编译器能够根据标签的Attribute自动识别资源类型,如果类型不对就会抛出异常,但在C#代码里检索到资源对象后,类型转换的事情就只能由我们自己来做了。
在XAML代码中向Resources添加资源时需要把正确的名称空间引入到XAML代码中。
xmlns:sys="clr-namespace:System;assembly=mscorlib"
定义资源:
<sys:Double x:Key="dbl">3.1415926</sys:Double>
在C#中使用资源:
Double val=(Double)this.FindResource("dbl");
//or, we can use
Double val=(Double)this.Resource["dbl"];
当资源被存储进资源词典后,我们可以通过两种方式来使用这些资源--静态方式和动态方式。
静态资源使用(StaticResource)指的是在程序载入内存时对资源的一次性使用,之后就不再去访问这个资源;动态资源使用(DynamicResource)指的是在程序运行过程中仍然会去访问资源。
明确称呼资源词典里的资源为WPF资源或对象资源,称呼应用程序的内嵌资源为程序集资源或二进制资源。程序中写在<Application.Resource>...</ApplicationResource>标签内的资源仍然是WPF资源而不是二进制资源。
Properties名称空间中的Resource.resx资源文件内容的组织形式也是“键-值”对,编译后,Resource.resx会形成Properties名称空间中的Resource类,使用这个类的方法或属性就能获取资源。为了让XAML编译器能够访问这个类,一定要把Resource.resx的访问级别由Internal改为public。
如果需要添加的资源不是字符串而是图标,图片,音频或视频,方法就不是使用Resource.resx了,WPF不支持这样做。在WPF中使用外部文件作为资源,仅需简单地将其加入项目即可。
如果想让外部文件编译进目标成为二进制资源,必须在属性窗口中把文件的BuildAction属性值设为Resource。
WPF对二进制资源的访问成为Pack URL路径。如:
<Image x;Name="ImageBg" Source="Resources/Images/Rafale.jpg" Stretch="Fill"/>
或:
<Image x:Name="ImageBg" Source="pack://application:,,,/Resources/Images/Rafale.jpg" Strech="Fill"/>
对应的C#代码:
Uri imgUri=new Uri@"Resources/Images/Rafale.jpg",UriKind.Relative);
this.ImageBg.Source=new BitmapImage(imgUri);
或:
Uri imgUir=new Uri(@"pack://application:,,,/Resources/Images/Rafale.jpg",UriKind.Absolute);
this.ImageBg.Source=new BitmapImage(imgUri);
基本上格式为:
pack://application,,,[/程序集名称;][可选版本号;][文件夹名称/]文件名
或简化为:
[文件夹名称/]文件名称
注意:
1)Pack URI使用从右向左的正斜线(/)表示路径;
2)缩减写法意味着相对路径,C#代码中的UriKind必须为Relative,而且代码根目录的/可以不用;
3)使用完整写法是绝对路径,C#代码中的UtiKind必须为Absolute并且代表根目录的/不能去掉;
4)使用相对路径可以借助类似DOS语法进行导航,比如./代表同级目录,../代表父级目录。