Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

在上一篇,介绍了Visual State Manager视觉状态管理器,其中涉及到控件的样式(Style)和模板(Template),本篇将详细介绍样式(Style)和模板(Template)在Silverlight项目中的应用,并介绍如何使用Blend设计样式(Style)和模板(Template)。

在LOB(Line-of-Business)企业级应用项目开发中,为了使项目的视觉效果多样化,不仅仅使用动画效果,而且经常还需要修改部分控件的样式(Style)和模板(Template)。 在Silverlight的控件包中,微软已经定义了默认控件样式和模板,开发人员可以在这些默认的代码上进行修改和调整,以达到项目需求。但是由于默认的控件样式和模板代码过于冗长,手工修改起来相对复杂和繁琐,对此,微软封装了一些新的功能在Blend中,方便开发人员和设计人员对模板和样式进行控制。在学习Blend控制样式(Style)和模板(Template)前,还是先快速了解一下样式(Style)和模板(Template)。

样式(Style),有HTML开发基础的朋友对传统的CSS样式表并不陌生,HTML将所有公用的属性代码汇集到CSS文件中,使用CSS控制页面的背景,控制表格的宽度,控制控件距离等。Silverlight中的样式(Style)和CSS相同,允许设计人员和开发人员将控件的公用属性定义到资源文件中,允许相同属性控件自由调用,这样不仅提高了代码的复用性,而且保证了控件外观在项目中的一致性。

模板(Template),模板的概念在传统的Web页面开发中已经被引入,早期Dreamweaver因为支持创建Web模板设计,吸引了不少Web开发者。Silverlight中同样引进了模板的概念。在Silverlight中,凡是继承自System.Windows.Controls命名控件的控件都有一套默认的模板,设计人员和开发人员可以基于默认模板的基础上进行修改,创建自定义模板。

样式(Style)和模板(Template)的定义

在Silverlight中,样式和模板定义是很简单的,因为很多属性已经被封装好,不需要自行创建,只需要调用就可以了。简单的演示代码:

Style:

1<UserControl.Resources>
2<Stylex:Key="TextBoxStyle"TargetType="TextBox">
3这里定义具体样式属性
4</Style>
5</UserControl.Resources>

Template:

1<UserControl.Resources>
2<ControlTemplatex:Key="TextBoxTemplate"TargetType="TextBox">

3<BorderBorderBrush="Orange"BorderThickness="3"CornerRadius="10"

4Background="Red">

5
这里定义具体模板
6</Border>
7</ControlTemplate>

8</UserControl.Resources>

样式(Style)和模板(Template)的使用

在Silverlight中样式(Style)和模板(Template)都属于控件资源,也就是说,两者都可以被定义在资源文件中,而在项目页面中,仅需使用Style和Template属性调用就可以了。

Style:

1<TextBoxStyle={"StaticResourceTextBoxStyle"}Text="样式测试"/>

Template:这个方法,也是Blend所支持的方法,下面我们看看实例,进一步理解。

1<TextBoxTemplate={"StaticResourceTextBoxTemplate"}Text="模板测试"/>

上面介绍了样式和模板的最基本的用法。在实际项目中,我们经常把模板(Template)定义在样式(Style)中,也就是将Template作为一个属性被赋值在Style中,这样当样式(Style)被应用在控件中时,新的模板也会同时加载。例如下面Button样式代码,<SetterProperty="Template"> Template是作为Style的属性被设置的:

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,TemplateExpression Blend实例中文教程(12) - 样式和模板快速入门Style,Template代码
1<ResourceDictionary>
2<Stylex:Key="ButtonStyle1"TargetType="Button">
3<SetterProperty="Background"Value="#FF1F3B53"/>
4<SetterProperty="Foreground"Value="#FF000000"/>
5<SetterProperty="Padding"Value="3"/>
6<SetterProperty="BorderThickness"Value="1"/>
7<SetterProperty="BorderBrush">
8<Setter.Value>
9<LinearGradientBrushEndPoint="0.5,1"StartPoint="0.5,0">
10<GradientStopColor="#FFA3AEB9"Offset="0"/>
11<GradientStopColor="#FF8399A9"Offset="0.375"/>
12<GradientStopColor="#FF718597"Offset="0.375"/>
13<GradientStopColor="#FF617584"Offset="1"/>
14</LinearGradientBrush>
15</Setter.Value>
16</Setter>
17<SetterProperty="Template">
18<Setter.Value>
19<ControlTemplateTargetType="Button">
20<Grid>
21<VisualStateManager.VisualStateGroups>
22<VisualStateGroupx:Name="CommonStates">
23<VisualStatex:Name="Normal"/>
24<VisualStatex:Name="MouseOver">
25<Storyboard>
26<DoubleAnimationUsingKeyFramesStoryboard.TargetName="BackgroundAnimation"Storyboard.TargetProperty="Opacity">
27<SplineDoubleKeyFrameKeyTime="0"Value="1"/>
28</DoubleAnimationUsingKeyFrames>
29<ColorAnimationUsingKeyFramesStoryboard.TargetName="BackgroundGradient"Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
30<SplineColorKeyFrameKeyTime="0"Value="#F2FFFFFF"/>
31</ColorAnimationUsingKeyFrames>
32<ColorAnimationUsingKeyFramesStoryboard.TargetName="BackgroundGradient"Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)">
33<SplineColorKeyFrameKeyTime="0"Value="#CCFFFFFF"/>
34</ColorAnimationUsingKeyFrames>
35<ColorAnimationUsingKeyFramesStoryboard.TargetName="BackgroundGradient"Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)">
36<SplineColorKeyFrameKeyTime="0"Value="#7FFFFFFF"/>
37</ColorAnimationUsingKeyFrames>
38</Storyboard>
39</VisualState>
40<VisualStatex:Name="Pressed">
41<Storyboard>
42<ColorAnimationUsingKeyFramesStoryboard.TargetName="Background"Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)">
43<SplineColorKeyFrameKeyTime="0"Value="#FF6DBDD1"/>
44</ColorAnimationUsingKeyFrames>
45<DoubleAnimationUsingKeyFramesStoryboard.TargetName="BackgroundAnimation"Storyboard.TargetProperty="Opacity">
46<SplineDoubleKeyFrameKeyTime="0"Value="1"/>
47</DoubleAnimationUsingKeyFrames>
48<ColorAnimationUsingKeyFramesStoryboard.TargetName="BackgroundGradient"Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)">
49<SplineColorKeyFrameKeyTime="0"Value="#D8FFFFFF"/>
50</ColorAnimationUsingKeyFrames>
51<ColorAnimationUsingKeyFramesStoryboard.TargetName="BackgroundGradient"Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
52<SplineColorKeyFrameKeyTime="0"Value="#C6FFFFFF"/>
53</ColorAnimationUsingKeyFrames>
54<ColorAnimationUsingKeyFramesStoryboard.TargetName="BackgroundGradient"Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)">
55<SplineColorKeyFrameKeyTime="0"Value="#8CFFFFFF"/>
56</ColorAnimationUsingKeyFrames>
57<ColorAnimationUsingKeyFramesStoryboard.TargetName="BackgroundGradient"Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)">
58<SplineColorKeyFrameKeyTime="0"Value="#3FFFFFFF"/>
59</ColorAnimationUsingKeyFrames>
60</Storyboard>
61</VisualState>
62<VisualStatex:Name="Disabled">
63<Storyboard>
64<DoubleAnimationUsingKeyFramesStoryboard.TargetName="DisabledVisualElement"Storyboard.TargetProperty="Opacity">
65<SplineDoubleKeyFrameKeyTime="0"Value=".55"/>
66</DoubleAnimationUsingKeyFrames>
67</Storyboard>
68</VisualState>
69</VisualStateGroup>
70<VisualStateGroupx:Name="FocusStates">
71<VisualStatex:Name="Focused">
72<Storyboard>
73<DoubleAnimationUsingKeyFramesStoryboard.TargetName="FocusVisualElement"Storyboard.TargetProperty="Opacity">
74<SplineDoubleKeyFrameKeyTime="0"Value="1"/>
75</DoubleAnimationUsingKeyFrames>
76</Storyboard>
77</VisualState>
78<VisualStatex:Name="Unfocused"/>
79</VisualStateGroup>
80</VisualStateManager.VisualStateGroups>
81<Borderx:Name="Background"Background="White"BorderBrush="{TemplateBindingBorderBrush}"BorderThickness="{TemplateBindingBorderThickness}"CornerRadius="3">
82<GridMargin="1"Background="{TemplateBindingBackground}">
83<Borderx:Name="BackgroundAnimation"Opacity="0"Background="#FF448DCA"/>
84<Rectanglex:Name="BackgroundGradient">
85<Rectangle.Fill>
86<LinearGradientBrushEndPoint=".7,1"StartPoint=".7,0">
87<GradientStopColor="#FFFFFFFF"Offset="0"/>
88<GradientStopColor="#F9FFFFFF"Offset="0.375"/>
89<GradientStopColor="#E5FFFFFF"Offset="0.625"/>
90<GradientStopColor="#C6FFFFFF"Offset="1"/>
91</LinearGradientBrush>
92</Rectangle.Fill>
93</Rectangle>
94</Grid>
95</Border>
96<ContentPresenterx:Name="contentPresenter"HorizontalAlignment="{TemplateBindingHorizontalContentAlignment}"Margin="{TemplateBindingPadding}"VerticalAlignment="{TemplateBindingVerticalContentAlignment}"Content="{TemplateBindingContent}"ContentTemplate="{TemplateBindingContentTemplate}"/>
97<Rectanglex:Name="DisabledVisualElement"Fill="#FFFFFFFF"RadiusX="3"RadiusY="3"IsHitTestVisible="false"Opacity="0"/>
98<Rectanglex:Name="FocusVisualElement"Stroke="#FF6DBDD1"StrokeThickness="1"RadiusX="2"RadiusY="2"Margin="1"IsHitTestVisible="false"Opacity="0"/>
99</Grid>
100</ControlTemplate>
101</Setter.Value>
102</Setter>
103</Style>
104</ResourceDictionary>

下面我们用一个简单的实例来理解Style(样式)和Template(模板)。

首先,我们创建一个新的项目StyleTemplateDemo作为演示。

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

打开MainPage,在主设计窗口中,添加三个按钮控件到该页面,

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

对于Button控件的样式属性控制,最简单的方法就是从右边Properties属性栏,

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

如果需要创建自定义样式,则需要按照以下步骤:

首先选中其中一个按钮控件,在左上角可以看到Button控件下拉菜单,

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

点击“[Button]”下拉菜单,选择“Edit Template”,然后选择“Edit a Copy”,

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

或者,可以在主设计窗口,使用鼠标右键选中控件,选择“Edit Template”,然后选择“Edit a Copy”,

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

选中“Edit a Copy”,系统会弹出提示窗口,询问“Create Style Resource”是否创建样式资源,

其中Name(Key)是样式名,以后调用该样式将使用这个Name;

Define in 有三个选择:

1. Application(应用),该选项是将该样式代码添加到App.Xaml文件中;

2. This document(当前文档),该选项是将该样式代码添加到当前编辑文档中,当前我们编辑MainPage.Xaml,如果选中此项,样式代码将被输出到该文件中;

3. Resource dictionary(资源目录),该选项是将该样式代码添加到自定义资源文件中,如果没有资源文件,可以点击“New”创建自定义资源文件;

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

在This document(当前文档)中,该选项有两个选择,

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

“UserControl:<no name>”,选中该选项样式代码将在当前文档创建<UserControl.Resources>,

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

调用是使用前面的基础调用代码:

1<ButtonMargin="114,197,0,228"Width="139"Content="Button"HorizontalAlignment="Left"d:LayoutOverrides="Width"Style="{StaticResourceButtonStyle1}"/>

“Button:<no name>”,选中该选项样式代码将创建在该控件资源下,

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

对比以上三种定义样式代码方式,第一种和第三种方法相对来说比较灵活,将样式代码放在公共资源文件中,方便其他页面相同属性控件调用;而第二种方法,仅供该文件中的相同属性控件调用。

这里我们Define in选择Application,定义样式代码到App.xaml中,点击确定后,系统会打开App.xaml文件,进入控件样式编辑状态,这时就可以对控件样式进行编辑。

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

当前主设计窗口打开文件为"App.xaml",因为该文件包含了要编辑的样式和模板代码。

在控件处于样式和模板编辑状态下,从Objects and Timeline窗口可以查看该控件模板的子部件,通过修改包含的子部件样式,来改变原按钮控件样式。

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

例如我们想改变Button的背景色,可以修改BackgroundGradient属性,从上图的Objects and Timeline中选中BackgroundGradient,

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

在右边Properties属性栏,修改颜色,即可看到在主设计窗口按钮的背景色在改变。

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

保存以上修改后,回到主设计窗口,能看到两个Button已经被应用了新的Button样式,

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

1<Gridx:Name="LayoutRoot"Background="White">
2<Buttonx:Name="bt1"Margin="254,151,247,0"Width="139"Content="按钮样式"Style="{StaticResourceButtonStyle1}"Height="55"VerticalAlignment="Top"/>
3<ButtonMargin="0,151,92,0"Width="139"Content="Button"HorizontalAlignment="Right"d:LayoutOverrides="Width"Height="55"VerticalAlignment="Top"/>
4<ButtonMargin="94,151,0,0"Width="139"Content="Button"HorizontalAlignment="Left"d:LayoutOverrides="Width"Style="{StaticResourceButtonStyle1}"Height="55"VerticalAlignment="Top"/>
5</Grid>

从代码中可以看出,使用Style="{StaticResourceButtonStyle1}" 的按钮,已经将默认Button样式替换为新的Button样式。如果想修改最后一个Button的样式,同样,把Style="{StaticResourceButtonStyle1}" 属性添加到Button中即可。在Blend中可以非常简单的应用新的样式到控件。

在需要被应用样式的Button控件上点击鼠标右键,然后选择“Edit Template”->“Apply Resource” ->选中当前需要被应用的样式,在主设计窗口即可看到控件样式的变化。

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

现在,我们切换左边的Objects and Timeline 到 States,当前选中的States是CommonStates组中的Normal, 阅读过上一篇VSM教程的,相信对这里并不陌生,Normal表示Button控件的正常视图状态。Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

这里我们可以看到,在主设计窗口,Button样式仍旧是紫色

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

当我们选中MouseOver视图状态时,主设计窗口Button样式,变成默认的样式。这说明,每个Visual State视觉状态都有自己独立样式,和上一篇讲述的控件每个视图状态都有独立性是相符的。

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

所以,要修改完整的一套控件样式,需要以控件的视图状态为基础,修改每个会引起控件视图产生变化的状态。这里,我们选中MouseOver后,切换Tab到 Objects and Timeline,

选中“BackgroundGradient”,修改Button控件在鼠标覆盖后的背景,

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

保存后,F5运行该例程,当鼠标放在Button上,自动会切换Button样式。

Normal状态:

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

MouseOver状态:

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

Pressed状态:

Expression Blend实例中文教程(12) - 样式和模板快速入门Style,Template

上图可以看出Pressed状态并没有改变,仍旧是默认样式。其样式修改方法与上面的方法相同,这里不再重复,大家可以按照以上方法修改。

对于控件样式的的控制,基本已经讲完。在下一篇将介绍Template模板的应用实例。