Silverlight 简明教程(3) -- 资源、样式控制、视觉状态以及部署
资源
Silverlight2中的页面元素的各个组成部分都可以分离出来作为资源的一部分,以方便复用。
比如我们为用户控件添加一个颜色资源:
<UserControl.Resources> <Color x:Key="Green">#F722FF00</Color> </UserControl.Resources>
然后我们需要在定义的按钮和所画的椭圆中使用{StaticResource KeyName}去使用该资源:
<Grid x:Name="LayoutRoot" Background="White"> <Button Height="56" Width="128" Content="Button" BorderThickness="2,2,2,2"> <Button.Background> <SolidColorBrush Color="{StaticResource Green}"/> </Button.Background> </Button> <Ellipse Height="56" HorizontalAlignment="Left" Margin="64,176,0,0" VerticalAlignment="Top" Width="112"> <Ellipse.Fill> <SolidColorBrush Color="{StaticResource Green}"/> </Ellipse.Fill> </Ellipse> </Grid>
效果如图:
样式控制
Silverlight2中支持使用样式,样式也是资源的一部分。样式使用Style标签来指定。
下面我们指定了一个针对Button类型的样式:
<UserControl.Resources> <Style x:Key="ButtonStyle1" TargetType="Button"> <Setter Property="Background" Value="#F722FF00" /> <Setter Property="Foreground" Value="#FFFF0000"/> <Setter Property="Padding" Value="3"/> <Setter Property="BorderThickness" Value="2"/> </Style> </UserControl.Resources>
然后我们新添加一个Button,通过使用与资源使用相同的语法来为新添加的一个Button使用该样式:
<Grid x:Name="LayoutRoot" Background="White"> <Canvas> <Button Width="128" Height="56" Canvas.Left="20" Canvas.Top="20" Style="{StaticResource ButtonStyle1}" Content="Button1" /> <Button Width="128" Height="56" Canvas.Left="20" Canvas.Top="80" Style="{StaticResource ButtonStyle1}" Content="Button2" /> </Canvas> </Grid>
最终效果:
上面所提到的资源和样式都是写在用户控件中,只能在用户控件的范围内使用。但如果要在整个应用程序中使用,则应该将样式资源定义在Silverlight项目的App.xaml中:
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="StyleSample.App"> <Application.Resources> <!-- Resources scoped at the Application level should be defined here. --> <Style x:Key="ButtonStyle1" TargetType="Button"> <Setter Property="Background" Value="#F722FF00" /> <Setter Property="Foreground" Value="#FFFF0000"/> <Setter Property="Padding" Value="3"/> <Setter Property="BorderThickness" Value="2"/> </Style> </Application.Resources> </Application>
但如果App.xaml中的样式与用户控件中的样式名称一样,用户控件中的样式会覆盖App.xaml中定义的样式。
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="StyleSample.Page" Width="640" Height="480"> <UserControl.Resources> <Style x:Key="ButtonStyle1" TargetType="Button"> <Setter Property="Foreground" Value="#FF000000"/> </Style> </UserControl.Resources> <Grid x:Name="LayoutRoot" Background="White"> <Canvas> <Button Width="128" Height="56" Canvas.Left="20" Canvas.Top="20" Style="{StaticResource ButtonStyle1}" Content="Button1" /> <Button Width="128" Height="56" Canvas.Left="20" Canvas.Top="80" Style="{StaticResource ButtonStyle1}" Content="Button2" /> </Canvas> </Grid> </UserControl>
效果如下图,可以看到按钮成了白底黑子,而不是App.xaml中的绿底红字。
视觉状态
视觉状态主要是将元素的逻辑与视觉呈现分离开来。它使得页面的换肤功能相对更容易。
理解视觉状态首先需要明白4个概念:部件、视觉状态、状态迁移和状态组。
- 部件 (Parts)
部件就是控件模板中被命名的元素。程序可以根据该名称定位到这些部件并进行逻辑操作。
比如上面的水印文本框, 水印就是一个部件,在焦点成为文本框时,水印将会消失。
- 状态 (States)
视觉状态就是控件定义的一系列的状态,如上面水印文本框的Focus和UnFocus。
- 状态过渡 (Transitions)
状态过渡就是指控件从一个状态过渡到另一个状态,如水印文本框从UnFocus状态过渡到Focus状态。在这其中可以使用Storyboard来定义动画效果。
- 状态组 (StateGroups)
状态组就是将控件所有的互斥状态房子啊同一组,最终其状态由所有组中的一个状态来共同决定。
比如还是上面的文本框,它有3个状态组:
Common:Normal、 MouseOver、 Disabled
Watermark:Unwatermarked、Watermarked
Focus:UnFocused、Focused
那么文本框的状态就必须从上面三个状态组中取一个值来定义。如没有任何操作在文本框的时候,其状态为Normal|Watermarked|UnFocused。
那么,在上面的基础上又引入了视觉状态(VisualStates)和视觉状态组(VisualStateGroups)的概念。
- 视觉状态(VisualState)
视觉状态就是指当控件处于某一个状态的时候的视觉效果。比如一个按钮在点击之后,他的边框将会变为不同的颜色。
- 视觉状态组(VisualStateGroups)
视觉状态组包括了互斥的视觉状态和所拥有的视觉状态的过渡。
通过使用视觉状态管理器(VisualStateManager)来管理视觉状态和视觉状态组,可以根据控件的逻辑改变控件的视觉效果。
更多关于视觉状态的信息,请参考 “部件与状态”模式。
下面对视觉状态所产生的XAML代码做简单说明,下面是上面例子中水印文本框中定义的视觉状态管理代码的一部分。
<Style TargetType="local:WatermarkedTextBox" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Extended" xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="local:WatermarkedTextBox"> <Grid x:Name="Root" > <vsm:VisualStateManager.VisualStateGroups> <vsm:VisualStateGroup x:Name="CommonStates"> <vsm:VisualStateGroup.Transitions> <vsm:VisualTransition GeneratedDuration="0" /> </vsm:VisualStateGroup.Transitions> <vsm:VisualState x:Name="Normal" /> <vsm:VisualState x:Name="MouseOver" /> <vsm:VisualState x:Name="Disabled"> <Storyboard> <DoubleAnimation Storyboard.TargetName="DisabledVisual"
Storyboard.TargetProperty="Opacity" To="0.5" Duration="0" /> </Storyboard> </vsm:VisualState> </vsm:VisualStateGroup> <vsm:VisualStateGroup x:Name="WatermarkStates"> <vsm:VisualStateGroup.Transitions> <vsm:VisualTransition GeneratedDuration="0" /> </vsm:VisualStateGroup.Transitions> <vsm:VisualState x:Name="Unwatermarked" /> <vsm:VisualState x:Name="Watermarked"> <Storyboard> <DoubleAnimation Storyboard.TargetName="ContentElement"
Storyboard.TargetProperty="Opacity" To="0" Duration="0" /> <DoubleAnimation Storyboard.TargetName="Watermark"
Storyboard.TargetProperty="Opacity" To="1" Duration="0" /> </Storyboard> </vsm:VisualState> </vsm:VisualStateGroup> <vsm:VisualStateGroup x:Name="FocusStates"> <vsm:VisualStateGroup.Transitions> <vsm:VisualTransition GeneratedDuration="0" /> <vsm:VisualTransition To="Focused" GeneratedDuration="0:0:0.1" /> </vsm:VisualStateGroup.Transitions> <vsm:VisualState x:Name="Unfocused" /> <vsm:VisualState x:Name="Focused"> <Storyboard> <DoubleAnimation Storyboard.TargetName="ContentElement"
Storyboard.TargetProperty="Opacity" To="1" Duration="0" /> <DoubleAnimation Storyboard.TargetName="Watermark"
Storyboard.TargetProperty="Opacity" To="0" Duration="0" /> <DoubleAnimation Storyboard.TargetName="FocusVisual"
Storyboard.TargetProperty="Opacity" To="1" Duration="0" /> </Storyboard> </vsm:VisualState> </vsm:VisualStateGroup> </vsm:VisualStateManager.VisualStateGroups> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
来看代码中的视觉状态组为WatermarkStates的这一部分:
<vsm:VisualStateGroup x:Name="WatermarkStates"> <vsm:VisualStateGroup.Transitions> <vsm:VisualTransition GeneratedDuration="0" /> </vsm:VisualStateGroup.Transitions> <vsm:VisualState x:Name="Unwatermarked" /> <vsm:VisualState x:Name="Watermarked"> <Storyboard> <DoubleAnimation Storyboard.TargetName="ContentElement"
Storyboard.TargetProperty="Opacity" To="0" Duration="0" /> <DoubleAnimation Storyboard.TargetName="Watermark"
Storyboard.TargetProperty="Opacity" To="1" Duration="0" /> </Storyboard> </vsm:VisualState> </vsm:VisualStateGroup>
代码最前面的vsm表示前缀,在Style中以xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"定义,表示所有以vsm开头的XAML语法所指定的属性需要在assembly为System.Windows.dll中定义过。
<vsm:VisualTransition GeneratedDuration="0" /> 定义了过渡该状态组的状态之间过渡的时间,这里设置为0,表示立即过渡到另一状态。
<vsm:VisualState x:Name="Watermarked"> <Storyboard> <DoubleAnimation Storyboard.TargetName="ContentElement"
Storyboard.TargetProperty="Opacity" To="0" Duration="0" /> <DoubleAnimation Storyboard.TargetName="Watermark"
Storyboard.TargetProperty="Opacity" To="1" Duration="0" /> </Storyboard> </vsm:VisualState>
Watermarked这个状态就通过Storyboard定义了一个效果,描述了在进入Watermarked状态时,其ContentElement属性文本立即变为透明(因为Duration为0),而Watermark属性则变为不透明。
综上所述可以看到,由于控件的状态需要在不同的状态组中取其互斥的一个值,然后将各个状态组中的目标状态的动画效果综合在一起,引发了在控件状态变化的时候视觉效果也发生了变化。于是我们可以通过设置一个控件模板来定义不同的样式和效果,而轻松的实现换肤功能。
部署
Silverlight项目的部署并不需要.NET Framework的支持,它的实际工作原理是通过HTTP将服务器上silverlight所生成的XAP压缩包发到客户端,由浏览器的silverlight插件去执行这个压缩包而绘制出最终效果。因此其部署就是完全如同Flash一般使用HTML标签中的object,然后定义好XAP包的路径就可以了。
一般来说,一个silverlight项目所编译生成的XAP包在项目文件下的bin的debug目录中:
通过在HTML中嵌入以下HTML代码,将其中的source的值改为所指定的XAP文件,就可以运行silverlight程序了。
<object data="data:application/x-silverlight," type="application/x-silverlight-2" width="100%" height="100%"> <param name="source" value="AnimationSample.xap"/> <param name="onerror" value="onSilverlightError" /> <param name="background" value="white" /> <param name="minRuntimeVersion" value="2.0.31005.0" /> <param name="autoUpgrade" value="true" /> <a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;"> <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight"
style="border-style: none"/> </a> </object>
注意上面代码中的minRuntimeVersion,他指定了运行程序所必须的最小的silverlight版本。如果不满足此条件,silverlight程序将可能不能正确运行。
而如果需要在IIS中部署silverlight程序的话,则必须要在IIS中的MIME中添加.xaml的解释,如下图。