WPF学习第十集-深入浅出话资源
Posted LisenYang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF学习第十集-深入浅出话资源相关的知识,希望对你有一定的参考价值。
我们把有用的东西称为资源。“兵马未动,粮草先行”-----程序中的各种数据就是算法的原料和粮草。程序中可以存放数据的地方有很多,可以放在数据库里、可以存储在变量里。介于数据库存储和变量存储之间,我们还可以把数据存储在程序主体之外的文件里。外部文件与程序主体分离,这就有可能丢失或者损坏,编译器允许我们把外部文件编译进程序主体、称为程序主体不可分割的一部分。这就是传统意义上的程序资源(也称为二进制资源)。
WPF不但支持程序级的传统资源,同时还推出了独具特色的对象级资源,每个界面元素都可以携带自己的资源并可被自己的子级元素共享。比如后面的章节我们会讲到模板、程序样式和主题就经常放在对象资源里面。这样一来,在WPF程序中数据就分为4个等级存储了:数据库里的数据相当于存放在仓库里面,资源文件里的数据就相当于放进了旅行箱里,WPF对象资源里面的数据相当于存放在携带的背包里,变量里面的数据相当于拿在手里。
1.1 WPF对象资源的定义和查找
每个WPF界面元素都有一个名为Resource的属性,这个属性继承至FrameworkElement类,其类型为ResourceDictionary。ResourceDictionary能够以键值对的形式存储资源,当要使用到某个资源的时候,使用键值对的形式获取资源对象。在保存资源时,ResourceDictionary视资源对象为Object类型,所以再使用资源时先要对资源对象进行类型转换,XAML编译器能够根据Attribute自动识别资源类型,如果类型不对就会抛出异常,但在C#中检索到资源对象之后,类型转换的事情就只能由我们自己来做了。
ResourceDictionary可以存储任意类型的对象。在XAML代码中向Resource添加资源时需要把正确的命名空间引入到XAML代码中,让我们来看一个例子:
[html] view plain copy print ?
- <Window x:Class="WpfApplication1.Window31"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:sys="clr-namespace:System;assembly=mscorlib"
- Title="Window31" FontSize="16" SizeToContent="Height">
- <Window.Resources>
- <ResourceDictionary>
- <sys:String x:Key="str">沉舟侧畔千帆过,病树前头万木春。</sys:String>
- <sys:Double x:Key="db">3.1415926</sys:Double>
- </ResourceDictionary>
- </Window.Resources>
- <StackPanel>
- <TextBlock Text=" StaticResource ResourceKey=str"></TextBlock>
- <!--<TextBlock Text="StaticResource ResourceKey=db"></TextBlock>-->
- </StackPanel>
- </Window>
首先我们将System命名空间引入XAML代码中并映射为sys名称空间,然后在Windows.Resource里面添加了两个资源条目,一个是string类型,一个是double类型。最后我们用两个textBlock来消费这两个资源(被注释掉的代码因为数据类型不匹配而抛出异常)。程序运行效果如下图:
因为在XAML代码里面可以对集合类容及标签扩展进行简写,所以上面代码更常见的书写格式是这样:
[html] view plain copy print ?
- <Window x:Class="WpfApplication1.Window31"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:sys="clr-namespace:System;assembly=mscorlib"
- Title="Window31" FontSize="16" SizeToContent="Height">
- <Window.Resources>
- <sys:String x:Key="str">沉舟侧畔千帆过,病树前头万木春。</sys:String>
- <sys:Double x:Key="db">3.1415926</sys:Double>
- </Window.Resources>
- <StackPanel>
- <TextBlock Text=" StaticResource str"></TextBlock>
- <!--<TextBlock Text="StaticResource ResourceKey=db"></TextBlock>-->
- </StackPanel>
- </Window>
这就好比每个界面元素都有自己的一个背包,里面可能装有各种各样的资源,使用的时候打开找一找,如果没有找到还可以去翻看上一层控件的背包,直至找到这个资源或报告没有这个资源为止。
如果想在C#代码里面使用XAML代码里面定义的资源,大概格式是这样:
[csharp] view plain copy print ?
- private void Window_Loaded(object sender, RoutedEventArgs e)
- string text = (string)this.FindResource("str");
- txt0.Text = text;
或者你明确知道资源放在那个资源字典里,就可以这样检索资源:
[csharp] view plain copy print ?
- private void Window_Loaded(object sender, RoutedEventArgs e)
- string text = (string)this.Resources["str"];
- txt0.Text = text;
你可能会想,如果把资源想CSS或者JS一样放在独立的文件夹里,使用时成套引用、重用时便于分发岂不更好?WPF的资源当然可以做到这一点;ResourceDictionary具有一个名为Source的属性,只要把包含资源定义的文件路径赋值给这个属性就一切搞定了!举个例子,http://wpf.codeplex.com中包含了很多官方/半官方的WPF资源,其中包括WPF工具包和一组非常漂亮的程序皮肤,这些皮肤以资源的形式放在XAML文件中,使用时仅需要将相应的XAML文件添加进项目并使用Source属性进行引用,你的程序就立刻变的光鲜照人。
[html] view plain copy print ?
- <ResourceDictionary Source="ShinyRed.xaml">
- </ResourceDictionary>
1.2 且“动”且“静”用资源
当资源被存储进资源词典之后,我们可以使用两种方式来使用这些资源-----静态方式和动态方式。Static和Dynamic两个词都是我们的老朋友了,当这对词同时出现的时候Static指的是程序的非执行状态而Dynamic指的是程序的运行状态。对于资源的使用,Static和Dynamic也是这个意思。静态资源使用StackResource指的是程序载入内存时对资源的一次性使用,之后就不在去访问这个资源了;动态资源(DynamicResource)使用指的是在程序运行过程中仍然回去访问资源。显然如果你确定某些资源在程序初始化的时候只使用一次、之后不会再改变,就应该使用StaticResource,而程序运行过程中还有可能改变资源应该以DynamicResource形式使用。拿程序的主题来举例,如果程序的皮肤在运行过程中始终不变,以Static形式来使用资源就可以了。如果在程序运行过程中允许用户更改皮肤或者配色方案则必须使用DynamicResource来使用资源。
请看下面这个例子,我在Windows资源字典里放置了两个TextBlock类型资源,并分别以StaticResource和DynamicResource方式使用之:
[html] view plain copy print ?
- <Window x:Class="WpfApplication1.Window32"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- Title="Window32" FontSize="16" WindowStyle="ToolWindow">
- <Window.Resources《深入浅出WPF》学习笔记之深入浅出话资源