在WPF和Silverlight中的控件模板支持自定义控件的观感所谓的外观指控件的视觉效果而感觉则是控件交互的响应性如在控件上按下鼠标控件获得焦点等状态的改变微软在Silverlight Beta 中引进了一个新的概念视觉状态管理(Visual State Manager)为我们创建交互性的控件模板提供了极大的方便接下来我将会用几篇文章来介绍一下Silverlight 中的视觉状态管理 在定义控件时我们需要严格区分控件的视觉效果和控件的逻辑这样当我们修改控件外观时将不会影响控件逻辑Silverlight Beta 中提出的部件和状态模型能够很好的解决这一问题本文我们先来看一些基本的概念 部件(Parts) 所谓的部件(Parts)是指在空间模板中元素控件逻辑将会控制这些部件来完成一些特定的控件但它并不关心这些部件的视觉效果如下图所示对于一个Silder控件来说 在上图中的Silder控件由四个部件构成一个名为HorizontalThumb的Thumb控件一个名为HorizontalLargeChangeIncrease的RepeatButton控件一个名为HorizontalLargeChangeDecrease的RepeatButton控件一个名为HorizontalTemplate的FrameworkElement元素这些元素都将会在控件逻辑中进行控制如当按下HorizontalLargeChangeIncrease时滑块将向右移动按下HorizontalLargeChangeDecrease时滑块将向左移动 需要注意的一点是并不是所有的控件都具有部件有些控件可能没有部件大家可以去查阅Silverlight SDK 视觉状态(Visual States) 视觉状态是指控件定义的一系列状态如MouseOverPressed等它代表了控件处于某一个特定的逻辑状态如下面这幅图中定义的CheckBox控件的一些视觉状态 默认状态下CheckBox控件将显示为Normal状态当CheckBox被选中时它将显示为Checked状态当Checked为nullCheckBox将显示为Indeterminate状态 控件的视觉状态在Silverlight 中会使用VisualState类来表示它的定义非常简单如下代码所示 public sealed class VisualState : DependencyObject { public VisualState(); public string Name { get; } public Storyboard Storyboard { get; set; } } 状态迁移(State Transitions) 状态迁移是指控件从一个状态过渡到另外一个状态如Button控件从MouseOver状态到Pressed状态这个过渡过程通过Storyboard来定义的动画 状态迁移在Silverlight 中使用VisualTransition类来表示它的定义如下代码所示 public class VisualTransition { public VisualTransition(); public Duration Duration { get; set; } public string From { get; set; } public Storyboard Storyboard { get; set; } public string To { get; set; } } 状态组(StateGroups) 状态组是把控件所有互斥的状态放在同一个组中这样一个状态它只能位于一个组中所谓的互斥是指控件不肯能同时具有该组中的两种状态如Checked和Unchecked两个状态不可能同时存在以CheckBox控件为例我们来看一下它的状态组 从上表中我们可以看到对于CheckBox控件来说它有三个状态组FocusStatesCommonStatesCheckStates一个CheckBox控件可以同时为FocusedMouseOver和Indeterminate状态因为它们处在不同的状态组现在对于这个问题 CheckBox控件的状态是什么?答案应该由三部分组成分别为三个状态组中的一个状态组是在Silverlight 中提出的一个新的概念它由VisualStateGroup类来提供其中除了状态组名属性外维护了一个视觉状态的集合和一个状态迁移的集合如下代码所示 public sealed class VisualStateGroup : DependencyObject { public VisualStateGroup(); public string Name { get; } public Collection<VisualState> States { get; set; } public Collection<VisualTransition> Transitions { get; set; } } 使用状态组是一个非常棒的模型在Beta 中CheckBox控件有种状态(其中Focus在Beta 中是作为部件而不是状态)这种状态是通过CommonStates和CheckStates组合而成的如PressedUncheckedMouseOverChecked等而在Beta 中加上FocusStates状态CheckBox控件总共只有种状态 控件的状态和状态组是通过TemplateVisualState特性来声明的如在CheckBox控件中的声明如下代码所示 [TemplateVisualStateAttribute(Name = ContentFocused GroupName = FocusStates)] [TemplateVisualStateAttribute(Name = MouseOver GroupName = CommonStates)] [TemplateVisualStateAttribute(Name = Focused GroupName = FocusStates)] [TemplateVisualStateAttribute(Name = Checked GroupName = CheckStates)] [TemplateVisualStateAttribute(Name = Unchecked GroupName = CheckStates)] [TemplateVisualStateAttribute(Name = Indeterminate GroupName = CheckStates)] [TemplateVisualStateAttribute(Name = Pressed GroupName = CommonStates)] [TemplateVisualStateAttribute(Name = Disabled GroupName = CommonStates)] [TemplateVisualStateAttribute(Name = Unfocused GroupName = FocusStates)] [TemplateVisualStateAttribute(Name = Normal GroupName = CommonStates)] public class CheckBox : ToggleButton { // } 视觉状态管理器 我们再来看一下视觉状态管理器的概念有了上面这些概念在Silverlight 中视觉状态管理是通过视觉状态管理器(Visual State Manager)来进行的Silverlight 中提供了VisualStateManager类如下所示 public class VisualStateManager : DependencyObject { public static DependencyProperty CustomVisualStateManagerProperty; public VisualStateManager(); public static VisualStateManager GetCustomVisualStateManager(DependencyObject obj); public static Collection<VisualStateGroup> GetVisualStateGroups(DependencyObject obj); public static bool GoToState(Control control string stateName bool useTransitions); protected virtual bool GoToStateCore(Control control FrameworkElement templateRoot string stateName VisualStateGroup group VisualState state bool useTransitions); public static void SetCustomVisualStateManager(DependencyObject obj VisualStateManager value); } 视觉状态管理器负责管理控件的状态和状态组以及状态的迁移 状态变化 外部事件触发将会引起状态的变化进而引发状态迁移整个过程如下流程图所示
总结 本文介绍了Silverlight 中视觉状态管理的一些基本概念下篇文章我们将结合实例看看如何使用视觉状态管理来定制控件的观感 |