转载自:http://www.it165.net/pro/html/201311/7923.html
前言
在学习开发XAML时,有时候画面上某些组件可能会需要设定一样的属性(如:我有三个TextBlock都需要设定为显示红色字体,文字大小要32),但是一个一个设定不仅浪费时间,如果要做修改时,也要对每一个组件都重复做同样的修改,耗时也费力。
而在XAML有一个资源的概念,可以把类似的这样的组件属性、样式做一个事先的定义,然后再去对组件做指定套用。
在此篇主要会以在页面资源(FrameworkElement.Resources)使用为主
资源(Resources)
如前言所述,有时候我们会遇到这样的需求,这个时候资源的概念便派上用场了!
透过资源,我们可以事先透过定义好要套用到组件上的属性,并且这总地亿的资源可以重复使用!
资源是一种共享、反复利用元素、属性的机制。
可以用来定义的资源包含:
样式(Style)与模板(Template)、笔刷(Brush)、故事版脚本(Storyboard)...等等,这些都各式是资源的一种
而以下我们会以介绍样式(Style)为主,因为大多时候我们主要是针对XAML的组件(Button、Image、TextBlock、TextBox...)属性做设定。
直接资源与应用程序资源
资源包含两种类型:直接资源与页面资源
直接资源:
FrameworkElement.Resources,或称页面资源,是针对单一页面做资源配置,更详细的说页面资源只能被用在单一XAML页面中的组件使用,在这边,控件的组件(Grid、StackPanel、Button、Rectangle等等)都包含Resources属性(继承自FrameworkElement),于是我们便可以在Resources标签中定义我们想要使用的资源。
拿下图来例子看的话,页面资源分别就是XAML页面A与页面B,而页面A中的资源定义只有页面A看的到,同理页面B的资源也只有页面B的组件看的到,页面A无法使用页面B中所定义的资源。
假若今天我的XAML页中的程序很大,这时在Grid中有资源,Button中有资源,并且我都需要做一些变动,这样不就要来来回回的移动调整了吗,所以建议把资源的定义放在Page,因为这样的好处是可以方便我们对所有的资源做一个管理。
应用程序资源:
Application.Resources,可以使资源的定义被整个Application所看到,如果我在应用程序资源定义的话,以上面图来看,的页面A与页面B,这两个XAML页面都可以使用我在应用程序资源事先定义Resources。
而在这边我们先介绍直接资源,应用程序资源的部分会再另一篇做介绍。
那么究竟使用资源是什么样的感觉呢?
以直接资源(页面资源)为范例:
我们在Grid组件下拉入两个TextBlock,然后我们透过Resources的定义来让TextBlock套用同时改变!
这是原先不使用Resources的程序代码:
1.
<
TextBlock
HorizontalAlignment
=
"Left"
VerticalAlignment
=
"Top"
FontSize
=
"32"
Foreground
=
"Red"
Margin
=
"310,411,0,0"
Text
=
"TextBlock"
/>
2.
<
TextBlock
HorizontalAlignment
=
"Left"
VerticalAlignment
=
"Top"
FontSize
=
"32"
Foreground
=
"Red"
Margin
=
"677,411,0,0"
Text
=
"TextBlock"
/>
再来是透过定义资源的方式:
01.
<
Grid.Resources
>
02.
<
Style
TargetType
=
"TextBlock"
>
03.
<
Setter
Property
=
"FontSize"
Value
=
"32"
/>
04.
<
Setter
Property
=
"Foreground"
Value
=
"Red"
/>
05.
<
Setter
Property
=
"HorizontalAlignment"
Value
=
"Left"
/>
06.
<
Setter
Property
=
"VerticalAlignment"
Value
=
"Top"
/>
07.
</
Style
>
08.
</
Grid.Resources
>
09.
<
TextBlock
Margin
=
"310,411,0,0"
Text
=
"TextBlock"
/>
10.
<
TextBlock
Margin
=
"677,411,0,0"
Text
=
"TextBlock"
/>
结果显示:
上面的范例中,原先我们对两个TextBlock都做了一样的属性设定,但是在使用资源时,我们则是透过Style标签的定义来让后面的TextBlock一次套用。
而由于是使用页面资源,我们需要让被定义的Style资源被Resources标签包覆住,因为在这个范例中,XAML非常少,且刚好两个TextBlock是属于Grid子标签,所以便利用Grid.Resources作为我们定义用的区块(但是再次提醒,一边会建议放在Page中,Page.Resources,最后会提到)。
好的,在这边我们进入此篇文章的另一个重点,样式(Style)资源
Style(样式)
样式主要用来定义XAML组件中的属性值,例如我的按钮要什么样的文字大小,文字字型,文字颜色等等属性。
样式也是一种资源,所以需被放在有Resources属性的卷标中。
以下让我们再看一次前面的程序代码:
1.
<
Grid.Resources
>
2.
<
Style
TargetType
=
"TextBlock"
>
3.
<
Setter
Property
=
"FontSize"
Value
=
"32"
/>
4.
<
Setter
Property
=
"Foreground"
Value
=
"Red"
/>
5.
<
Setter
Property
=
"HorizontalAlignment"
Value
=
"Left"
/>
6.
<
Setter
Property
=
"VerticalAlignment"
Value
=
"Top"
/>
7.
</
Style
>
8.
</
Grid.Resources
>
Style:
是定义样式用的卷标,其中TargetType这个属性是用来指定你设定的组件,但是TargetType因为指定组件,所以全部在这个XAML页面下的组件都会被套用。
<Style TargetType="TextBlock">
已上面这段程序代码来看,代表着我要对所有TextBlock的组件套用这个样式
Setter:
设定Style中TargetType所指定的组件要变动的属性,要改变的方式则是透过Property指定属性,Value修改参数,以上面的例子来看:
<Setter Property="FontSize" Value="32"/>
修改字体就是TextBlock的FontSize大小为32,所以想要定义属性即可以透过这个Setter标签来完成
那么回到先前所提到的,TargetType因为指定组件,所以全部在这个XAML页面下的组件都会被套用,代表着我要对所有TextBlock的组件套用这个样式。
如果今天我只要对特定的TextBlock修改要怎么办?
使用X:Key与StaticResource延伸标记修改特定组件的属性
这次,我们来修改一下上面的范例,改成只要对左边的TextBlock显示红色,右边的TextBlock则显示黄色文字。
01.
<
Grid.Resources
>
02.
<
Style
TargetType
=
"TextBlock"
x:Key
=
"RedColor"
>
03.
<
Setter
Property
=
"FontSize"
Value
=
"32"
/>
04.
<
Setter
Property
=
"Foreground"
Value
=
"Red"
/>
05.
<
Setter
Property
=
"HorizontalAlignment"
Value
=
"Left"
/>
06.
<
Setter
Property
=
"VerticalAlignment"
Value
=
"Top"
/>
07.
</
Style
>
08.
<
Style
TargetType
=
"TextBlock"
x:Key
=
"YellowColor"
>
09.
<
Setter
Property
=
"FontSize"
Value
=
"32"
/>
10.
<
Setter
Property
=
"Foreground"
Value
=
"Yellow"
/>
11.
<
Setter
Property
=
"HorizontalAlignment"
Value
=
"Left"
/>
12.
<
Setter
Property
=
"VerticalAlignment"
Value
=
"Top"
/>
13.
</
Style
>
14.
</
Grid.Resources
>
15.
<
TextBlock
Margin
=
"310,411,0,0"
Text
=
"TextBlock"
Style
=
"{StaticResource RedColor}"
/>
16.
<
TextBlock
Margin
=
"677,411,0,0"
Text
=
"TextBlock"
Style
=
"{StaticResource YellowColor}"
/>
在上面你会看到,我们增加了新的程序代码,在Style中一个叫做X:Key的关键词与TextBlock中加入Style="{StaticResource xxx}"
X:Key:
在Style中加入这段程序,代表我要对这个资源指定索引键,而这个索引键可以做为之后与个别组件做样式的参考
Style="{StaticResource xxx}":
StaticResource 是一种延伸标记,透过这串语法,把先前所设定的X:Key的索引键做设定,可以取得事先定义好的Resources属性
所以在上面的范例中我们分别定义了YellowColor的样式与RedColor的样式,并把Key值分别指定到两个TextBlock的Style="{StaticResource xxx}中。
透过这样一个对样式
1.指定x:key与在组件中
2.在组件中设定Style,并做StaticResource 延伸标记参考x:key至我们事先定义好的Style资源
即可完成。
资源继承
在上面的X:Key范例中,两个TextBlock的差异只在颜色,而为了修改颜色,指定到不同的TextBlock,所以我们透过X:Key与StaticResource延伸标记来完成,但是你会看到有重复的Code,而这样就违背了我们原先的美意,因此在这边要介绍资源的继承,来让重复的XAML可以减少
使用BasedOn
BasedOn就如同对象导向中的继承概念一样,可以把妇类别的功能与成员属性继承下来:
01.
<
Grid.Resources
>
02.
<
Style
TargetType
=
"TextBlock"
x:Key
=
"Normal"
>
03.
<
Setter
Property
=
"FontSize"
Value
=
"32"
/>
04.
<
Setter
Property
=
"Foreground"
Value
=
"Red"
/>
05.
<
Setter
Property
=
"HorizontalAlignment"
Value
=
"Left"
/>
06.
<
Setter
Property
=
"VerticalAlignment"
Value
=
"Top"
/>
07.
</
Style
>
08.
<
Style
TargetType
=
"TextBlock"
x:Key
=
"YellowColor"
BasedOn
=
"{StaticResource Normal}"
>
09.
<
Setter
Property
=
"Foreground"
Value
=
"Yellow"
/>
10.
</
Style
>
11.
<
Style
TargetType
=
"TextBlock"
x:Key
=
"RedColor"
BasedOn
=
"{StaticResource Normal}"
>
12.
<
Setter
Property
=
"Foreground"
Value
=
"Red"
/>
13.
</
Style
>
14.
</
Grid.Resources
>
15.
<
TextBlock
Margin
=
"310,411,0,0"
Text
=
"TextBlock"
Style
=
"{StaticResource RedColor}"
/>
16.
<
TextBlock
Margin
=
"677,411,0,0"
Text
=
"TextBlock"
Style
=
"{StaticResource YellowColor}"
/>
X:Key="Normal"的样式就是TextBlock共同的属性设定,为了能够辨别到父样式而继承下来,所以才会需要X:Key="Normal"
而下面的YellowColor与RedColor索引键样式则是透过BasedOn与StaticResource延伸标记继承下来,并加入新的属性样式,透过这样的模式减少重复的属性设定!
为了呼应我们前面提到的资源可重复使用性,这边我而外再加入一个TextBlock,并对他套用YellowColor这个样式,如下程序代码与结果,即便是有索引键的资源也是可以重复给别的组件使用!
01.
<
Grid.Resources
>
02.
<
Style
TargetType
=
"TextBlock"
x:Key
=
"Normal"
>
03.
<
Setter
Property
=
"FontSize"
Value
=
"32"
/>
04.
<
Setter
Property
=
"HorizontalAlignment"
Value
=
"Left"
/>
05.
<
Setter
Property
=
"VerticalAlignment"
Value
=
"Top"
/>
06.
</
Style
>
07.
<
Style
TargetType
=
"TextBlock"
x:Key
=
"YellowColor"
BasedOn
=
"{StaticResource Normal}"
>
08.
<
Setter
Property
=
"Foreground"
Value
=
"Yellow"
/>
09.
</
Style
>
10.
<
Style
TargetType
=
"TextBlock"
x:Key
=
"RedColor"
BasedOn
=
"{StaticResource Normal}"
>
11.
<
Setter
Property
=
"Foreground"
Value
=
"Red"
/>
12.
</
Style
>
13.
</
Grid.Resources
>
14.
<
TextBlock
Margin
=
"310,411,0,0"
Text
=
"TextBlock"
Style
=
"{StaticResource YellowColor}"
/>
15.
<
TextBlock
Margin
=
"677,411,0,0"
Text
=
"TextBlock"
Style
=
"{StaticResource RedColor}"
/>
16.
<
TextBlock
Margin
=
"983,411,0,0"
Text
=
"TextBlock"
Style
=
"{StaticResource YellowColor}"
/>
把页面资源放在Page.Resources中
最后,在前面提到如果是单一页面的话,基本上会建议把Resources放在Page,因为Page是XAML页面的根,所以可以确保我整个页面下的组件根可能被指定套上资源,另外一个好处则是,方便所以的样式资源可以放在一起统一管理。
所以如下的XAML程序代码,便是移动到Page的Resources下,整个Windows 8 App的XAML档最外层是Page,所以我们在这边加入了Page.Resources的卷标,并把Style样式定义包覆在其中。
01.
<
Page.Resources
>
02.
<
Style
TargetType
=
"TextBlock"
x:Key
=
"Normal"
>
03.
<
Setter
Property
=
"FontSize"
Value
=
"32"
/>
04.
<
Setter
Property
=
"HorizontalAlignment"
Value
=
"Left"
/>
05.
<
Setter
Property
=
"VerticalAlignment"
Value
=
"Top"
/>
06.
</
Style
>
07.
<
Style
TargetType
=
"TextBlock"
x:Key
=
"YellowColor"
BasedOn
=
"{StaticResource Normal}"
>
08.
<
Setter
Property
=
"Foreground"
Value
=
"Yellow"
/>
09.
</
Style
>
10.
<
Style
TargetType
=
"TextBlock"
x:Key
=
"RedColor"
BasedOn
=
"{StaticResource Normal}"
>
11.
<
Setter
Property
=
"Foreground"
Value
=
"Red"
/>
12.
</
Style
>
13.
</
Page.Resources
>
14.
<
Grid
Background
=
"{StaticResource ApplicationPageBackgroundThemeBrush}"
HorizontalAlignment
=
"Left"
Width
=
"1366"
>
15.
<
TextBlock
Margin
=
"380,397,0,0"
Text
=
"TextBlock"
Style
=
"{StaticResource YellowColor}"
/>
16.
<
TextBlock
Margin
=
"614,397,0,0"
Text
=
"TextBlock"
Style
=
"{StaticResource RedColor}"
/>
17.
<
TextBlock
Margin
=
"832,397,0,0"
Text
=
"TextBlock"
Style
=
"{StaticResource YellowColor}"
/>
18.
</
Grid
>
结论
善用资源可以让你的XAML页面整齐,舍去重复的程序代码,同时若你要重修调整或修改维护你的XAML程序时,也可以加快你的修改速度(因为你不再需要一个一个去修改)。