打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
谈谈Silverlight 2中的视觉状态管理 Part2-李会军

谈谈Silverlight 2中的视觉状态管理 Part2

Author:李会军

Date:2008年8月14日

概述

在WPF 和Silverlight 中的控件模板支持自定义控件的观感,所谓的外观,指控件的视觉效果;而感觉则是控件交互的响应性,如在控件上按下鼠标、控件获得焦点等状态的改变。微软在Silverlight 2 Beta 2 中引进了一个新的概念视觉状态管理(Visual State Manager ),为我们创建交互性的控件模板提供了极大的方便。接下来我将会用几篇文章来介绍一下Silverlight 2 中的视觉状态管理。

本文为该系列第二篇,介绍如何利用Silverlight 2 中的视觉状态管理来定制控件观感。在前一篇我们介绍了视觉状态管理中的一些基本概念,下面将通过一个实例来展示如果利用视觉状态管理来定制控件的观感,最终我们完成的示例效果如下图所示:

本文中的示例使用了这篇文章中的代码

定义控件模板

我们现在先来定义CheckBox 控件的模板,即上篇文章中所介绍的部件,如下代码所示:

<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 )负责管理控件的状态和状态组以及状态的迁移,所以我们所有的视觉状态组、视觉状态迁移、视觉状态等都通过它来管理,在XAML 定义时,它们之间的架构关系如下:

在引用VisualStateManager 之前,需要先引入命名空间,这是Silverlight 2 Beta 2 的一个已知Bug 。如下代码所示:

xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"

接下来我们定义视觉状态组,在上篇文章中我们就介绍过CheckBox 的状态组,总共有三个: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 才能够找到相应的状态;二是故事板:指定状态变化时的视觉呈现。

现在我们来实现每一个状态,对于Normal 状态,不用作任何定义,因为它的定义与控件的基础状态一致,如下代码所示:

<!-- Normal State --><vsm:VisualState x:Name="Normal"></vsm:VisualState>

Normal 状态效果如下图所示:

定义MouseOver 视觉状态,当鼠标移上时高亮显示Glow ,修改Opacity 属性从0 到1 ,如下代码所示:

<!-- MouseOver State --><vsm:VisualState x:Name="MouseOver"><Storyboard><DoubleAnimationStoryboard.TargetName="Glow"Storyboard.TargetProperty="Opacity"Duration="0" To="1"/></Storyboard></vsm:VisualState>

MouseOver 状态效果如下图所示:

定义Pressed 视觉状态,按下鼠标时,改变HighlightBorder 的Opacity 属性,并且修改InnerBorder 的边框渐变,如下代码所示:

<!-- Pressed State --><vsm:VisualState x:Name="Pressed"><Storyboard><DoubleAnimationStoryboard.TargetName="HighlightBorder"Storyboard.TargetProperty="Opacity"Duration="0" To=".6"/><ColorAnimationStoryboard.TargetName="InnerBorder"Storyboard.TargetProperty="(Border.BorderBrush).(GradientBrush.GradientStops)[0].(GradientStop.Color)"Duration="0" To="#FF000000"/><ColorAnimationStoryboard.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><DoubleAnimationStoryboard.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 视觉状态组中有三个状态:Unchecked 、Checked 、Indeterminate 。其中Unchecked 与我们上面介绍Normal 状态是一致的,所以不用设置故事板。接下来定义Checked 视觉状态,如下代码所示:

<!-- Checked State --><vsm:VisualState x:Name="Checked"><Storyboard><DoubleAnimationStoryboard.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><DoubleAnimationStoryboard.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 来管理控件的视觉状态,在Silverlight 2 中视觉状态管理的强大之处还在于我们可以可视化的进行定制,下篇文章我讲解如何使用Expression Blend 定义视觉状态,希望本文对大家有用。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
WPF模拟Office2010文件菜单的TabControl模板
Silverlight DataGrid 多重表头实现
【WPF学习】第六十六章 支持可视化状态
WPF: WPF 中的 Triggers 和 VisualStateManager
通通玩blend美工
一步一步学Silverlight 2系列(32):图形图像综合实例—“功夫之王”剧照播放
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服