本文为该系列第 2篇介绍如何利用Silverlight 2中视觉状态管理来定制Control控件观感在前篇我们介绍了视觉状态管理中些基本概念下面将通过个例子来展示如果利用视觉状态管理来定制Control控件观感最终我们完成举例效果如下图所示:
本文中举例使用了这篇文章中代码
定义Control控件模板 我们现在先来定义CheckBoxControl控件模板即上篇文章中所介绍部件如下代码所示:
<ControlTemplate TargetType="CheckBox">
<StackPanel x:Name="Root" >
<!-- OuterBorder -->
<Border Width="20" Height="20">
<!-- InnerBorder -->
<Border x:Name="InnerBorder">
<Grid>
<!-- Higlight-->
<Border x:Name="HighlightBorder"> </Border>
<!-- Glow -->
<Rectangle x:Name="Glow" Opacity="0"></Rectangle>
<!-- Checkmark Graphic-->
<Path x:Name="Checkmark" Opacity="0"></Path>
<!-- Indeterminate Rect-->
<Rectangle x:Name="IndeterminateRect" Opacity="0"></Rectangle>
</Grid>
</Border>
</Border>
<!-- ContentPresenter -->
<ContentPresenter />
</StackPanel>
</ControlTemplate>
为了减少代码这里去掉了些属性只是给出了必备些部件名称现在我们运行后可以看到虽然CheckBox样式有了但它并没有任何交互效果如点击鼠标后CheckBox并没有选中定义视觉状态组 我们知道视觉状态管理器(VisualStateManager)负责管理Control控件状态和状态组以及状态迁移所以我们所有视觉状态组、视觉状态迁移、视觉状态等都通过它来管理在XAML定义时它们的间架构关系如下:
在引用VisualStateManager的前需要先引入命名空间这是Silverlight 2 Beta 2个已知Bug如下代码所示:
xmlns:vsm="clr-:.Windows;assembly=.Windows"
接下来我们定义视觉状态组在上篇文章中我们就介绍过CheckBox状态组总共有 3个:FocusStates、CommonStates、CheckStates这里我们只定义CommonStates和CheckStates状态组大家可以自行定义FocusStates状态组如下代码所示:<vsm:VisualStateManager.VisualStateGroups>
<!-- CommonStates StateGroup-->
<vsm:VisualStateGroup x:Name="CommonStates">
</vsm:VisualStateGroup>
<!-- CheckStates StateGroup-->
<vsm:VisualStateGroup x:Name="CheckStates">
</vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
这里需要为每个视觉状态组指定名称且名称是固定定义视觉状态 现在我们添加视觉状态到状态组在CommonStates和CheckStates状态组中总共有7个状态如下表所示:
首先我们来定义CommonStates状态组代码如下所示:
<!-- CommonStates StateGroup-->
<vsm:VisualStateGroup x:Name="CommonStates">
<!-- Normal State -->
<vsm:VisualState x:Name="Normal">
</vsm:VisualState>
<!-- MouseOver State -->
<vsm:VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation/>
</Storyboard>
</vsm:VisualState>
<!-- Pressed State -->
<vsm:VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimation/>
</Storyboard>
</vsm:VisualState>
<!-- Disabled State -->
<vsm:VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation/>
</Storyboard>
</vsm:VisualState>
</vsm:VisualStateGroup>
对于每个视觉状态主要有两部分组成:是命名:我们需要为视觉状态指定个名称且名称为固定这样VisualStateManager才能够找到相应状态; 2是故事板:指定状态变化时视觉呈现现在我们来实现每个状态对于Normal状态不用作任何定义它定义和Control控件基础状态致如下代码所示:
<!-- Normal State -->
<vsm:VisualState x:Name="Normal">
</vsm:VisualState>
Normal状态效果如下图所示:定义MouseOver视觉状态当鼠标移上时高亮显示Glow修改Opacity属性从0到1如下代码所示:
<!-- MouseOver State -->
<vsm:VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="Glow"
Storyboard.TargetProperty="Opacity"
Duration="0" To="1"/>
</Storyboard>
</vsm:VisualState>
MouseOver状态效果如下图所示:定义Pressed视觉状态按下鼠标时改变HighlightBorderOpacity属性并且修改InnerBorder边框渐变如下代码所示:
<!-- Pressed State -->
<vsm:VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="HighlightBorder"
Storyboard.TargetProperty="Opacity"
Duration="0" To=".6"/>
<ColorAnimation
Storyboard.TargetName="InnerBorder"
Storyboard.TargetProperty="(Border.BorderBrush).
(GradientBrush.GradientStops)[0].(GradientStop.Color)"
Duration="0" To="#FF000000"/>
<ColorAnimation
Storyboard.TargetName="InnerBorder"
Storyboard.TargetProperty="(Border.BorderBrush).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Duration="0" To="#FF000000"/>
</Storyboard>
</vsm:VisualState>
Pressed状态效果如下图所示:定义Disabled视觉状态设置Root元素Opacity属性为0.5如下代码所示:
<!-- Disabled State -->
<vsm:VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="Root"
Storyboard.TargetProperty="Opacity"
Duration="0" To=".5"/>
</Storyboard>
</vsm:VisualState>
Disabled状态效果如下图所示:现在我们来定义CheckStates视觉状态组如下代码所示:
<!-- CheckStates StateGroup-->
<vsm:VisualStateGroup x:Name="CheckStates">
<!-- Unchecked State -->
<vsm:VisualState x:Name="Unchecked"/>
<!-- Checked State -->
<vsm:VisualState x:Name="Checked">
<Storyboard>
<DoubleAnimation/>
</Storyboard>
</vsm:VisualState>
<!-- Indeterminate State -->
<vsm:VisualState x:Name="Indeterminate">
<Storyboard>
<DoubleAnimation/>
</Storyboard>
</vsm:VisualState>
</vsm:VisualStateGroup>
在CheckStates视觉状态组中有 3个状态:Unchecked、Checked、Indeterminate其中Unchecked和我们上面介绍Normal状态是致所以不用设置故事板接下来定义Checked视觉状态如下代码所示:<!-- Checked State -->
<vsm:VisualState x:Name="Checked">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="Checkmark"
Storyboard.TargetProperty="Opacity"
Duration="0" To="1"/>
</Storyboard>
</vsm:VisualState>
Checked视觉状态效果如下图所示:定义Indeterminate视觉状态在CheckBox使用时要呈现该状态必须设置IsThreeState属性为True它定义如下代码所示:
<!-- Indeterminate State -->
<vsm:VisualState x:Name="Indeterminate">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="IndeterminateRect"
Storyboard.TargetProperty="Opacity"
Duration="0" To="1"/>
</Storyboard>
</vsm:VisualState>
Indeterminate视觉状态效果如下图所示:定义视觉状态迁移 在上面部分中我们定义了所有视觉状态但是各个状态的间状态过渡效果并没有显示出来现在我们定义视觉状态迁移视觉状态迁移是定义在每个视觉状态组中在Transitions下我们可以定义系列状态迁移定义CheckStates状态组视觉状态迁移如下代码所示:
<!-- CheckStates Transitions-->
<vsm:VisualStateGroup.Transitions>
<vsm:VisualTransition Duration="0:0:.2" />
</vsm:VisualStateGroup.Transitions>
这里Duration定义了状态迁移需要时间长度这里定义视觉状态迁移是默认对所有状态都是用同时VisualTransition还允许我们针对特殊状态进行特别处理它为我们提供了From和To属性来指定特定状态可以只定义其中个或者两者都定义:如在CommonStates状态组中视觉状态迁移代码定义如下:
<!-- CommonStates Transitions-->
<vsm:VisualStateGroup.Transitions>
<vsm:VisualTransition Duration="0:0:.5" />
<vsm:VisualTransition Duration="0:0:0.8" To="MouseOver"/>
<vsm:VisualTransition Duration="0:0:0.2" From="Pressed"/>
<vsm:VisualTransition Duration="0" From="MouseOver" To="Pressed"/>
</vsm:VisualStateGroup.Transitions>
可以看到除了定义默认状态迁移的外我们还为MouseOver和Pressed状态定义了特定迁移效果整理总结 本文我们通过自定义个CheckBox外观讲解了如何使用VisualStateManager来管理Control控件视觉状态在Silverlight 2中视觉状态管理强大的处还在于我们可以可视化进行定制下篇文章我讲解如何使用Expression Blend定义视觉状态希望本文对大家有用
最新评论