Silverlight中的ControlTemplate(2)
Silverlight中的ControlTemplate介绍了ControlTemplate的相关的几个知识,这篇继续介绍剩余的内容
上文我们已经为Tooltip的ControlTemplate添加了视觉状态管理,结构如下:
<ControlTemplate TargetType="ToolTip"><Border><VisualStateManager.VisualStateGroups><VisualStateGroup x:Name="OpenStates"><VisualState x:Name="Closed"><Storyboard><ColorAnimation ...></ColorAnimation></Storyboard></VisualState><VisualState x:Name="Open"><Storyboard><ColorAnimation ...></ColorAnimation></Storyboard></VisualState></VisualStateGroup></VisualStateManager.VisualStateGroups></Border></ControlTemplate>
在应用了VisualState的ControlTemplate中ToolTip中,当你的ToolTip状态为Open时,直到1秒钟之后你才会看到设置的动画效果,
因为在默认状态下,动画要在1秒后才开始。如果需要立即体验到这种动画效果,这就用到了视觉状态迁移这个概念。
VisualTransition
把VisualTransition添加到ControlTemplate中,可以指定动画的延迟时间,从而使一种状态平滑的转移到另一种状态。 VisualTransition常用的属性为From【从哪个状态开始】,To【迁移到何种状态】,GeneratedDuration【间隔时长】。
以ToolTip为例,下面的Xaml表示当ToolTip进入打开状态时需要百分之一秒的时间<VisualTransition To="Open" GeneratedDuration="0:0:0.1" />
通过设置 To 和 From 属性,可以设置过渡的时间。
<VisualTransition From="Open" To="Closed" GeneratedDuration="0:0:0.5"/>
可以将VisualTransition限制为仅应用于某些状态,SDK上有关于这个限制的说明
VisualStateGroup
如果要应用多个 VisualTransition,则可以在VisualStateGroup.Transitions属性中进行设置.
<VisualStateGroup.Transitions><VisualTransition To="Closed"GeneratedDuration="0:0:0.1" /><VisualTransition Form="Open" To="Closed"GeneratedDuration="0:0:0.2" /></VisualStateGroup.Transitions>
这里需要注意2点:如果From,To里面设置的是VisualStateGroup里不存在的视觉状态名称,则会忽略该VisualTransition。
在 VisualStateGroup 中可以有多个引用同一状态的 VisualTransition对象,但是将按上图中指定的顺序使用它们,
因为在ToolTip中仅仅有2个视觉状态,不够直观,这里我们引用Button的视觉状态进行说明
<VisualTransition To="MouseOver"GeneratedDuration="0:0:0.1" /><VisualTransition From="Pressed" To="MouseOver"GeneratedDuration="0:0:0.2" />当Button从Pressed状态转换为MouseOver时,使用第2个视觉迁移,从非Pressed状态进入MouseOver时,则会使用第1个视觉状态。
在VisualTransition 包含还一个当控件转换状态时开始时的 Storyboard属性:
<VisualTransition From="MouseOver" To="Normal"GeneratedDuration="0:0:1.5"><Storyboard><ColorAnimationUsingKeyFrames …/></Storyboard></VisualTransition>
TemplatePartAttribute
上文在结束时提到了TemplateVisualStateAttribute这个特性,其实还有一个比较重要的特性TemplatePartAttribute,
有时候控件的内部逻辑需要对ControlTemplate中某个FrameworkElement进行事件处理,这时候就出现了控件协定这个概念。
在Silverlight中,控件使用 TemplatePartAttribute传递期望使用的元素的类型,以及元素应具有的名称。
如果你看ListBox的定义就会看到:
这个概念其实很好解释的,以ListBox为例,它内部的逻辑需要在其ContentTemplate中找到Name属性为ScrollViewer的ScrollViewer。
查看ListBox的ControlTemplate,你会看到这部分的XAML
<ControlTemplate TargetType="ListBox">...<Border ><ScrollViewer x:Name="ScrollViewer" ><ItemsPresenter/></ScrollViewer></Border>...</ControlTemplate>
好了,这篇暂时写到这里,最后结合两篇文章控件ControlTemplate中涉及的VSM的相关知识:
<ControlTemplate TargetType="..."><Grid><VisualStateManager.VisualStateGroups><VisualStateGroup.Transitions><VisualTransition From="" GeneratedDuration=""><VisualTransition From="" GeneratedDuration=""></VisualStateGroup.Transitions><VisualStateGroup x:Name="CommonStates"><VisualState x:Name="Normal"/><VisualState x:Name="Disabled"><Storyboard></VisualState></VisualStateGroup></VisualStateManager.VisualStateGroups><!--Other FrameworkElement-->
...</Grid></ControlTemplate>