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