【翻译】VSM 和触发器
原文:The VisualStateManager and Triggers
Author:Carole Snyder
Silverlight 推出了可视化状态管理器( Visual State Manager ),它使得控件模版作者更方便地指定依赖可视化状态的控件外观。WPF Toolkit 附带了一个可视化状态管理器( Visual State Manager ),WPF 的下个版本将会加入 VSM。可以理解地,VisualStateManager 的引进带来了问题:何时使用 VSM 代替触发器,何时使用触发器会更适合。本博文尝试解决这个问题:更多对如何使用可视化状态管理器( VisualStateManager )的深入讨论在这里。
可视化状态管理器( VisualStateManager )支持 parts 和 states 模型,控件作者使可视化状态在控件模版中形式化的一种方法。可视化状态管理器( VisualStateManager )使控件作者能够管理一个控件的不同状态并且为设计工具提供了一个方法,比如 Microsoft Blend 支持通过控件的可视化状态自定义它的外观。在 parts 和 states 模型被引进之前,普遍地,当它改变了可视化状态,控件模版作者使用触发器来改变控件的外观。下面的控件模版中,当鼠标悬停在按钮上面或者按钮被按压时,使用触发器来改变按钮的 border 颜色。
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Fill="{TemplateBinding BorderBrush}"/>
<Ellipse x:Name="ButtonShape"
Margin="5"
Fill="{TemplateBinding Background}"/>
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid> <ControlTemplate.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="BorderBrush"
Value="Cyan"/>
</Trigger>
<Trigger Property="IsPressed"
Value="True">
<Setter Property="BorderBrush"
Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
在这个模型中,没有关于什么是可视化状态正式的协议,这里只有定义在控件里的一些用来改变控件外观的属性。 A control that follows the parts and control model proactively communicates its visual states to control template authors. 当一个控件使用可视化状态管理器( VisualStateManager )来改变它的可视化状态,它就期望 控件模版(ControlTemplate )使用 可视化状态管理器( VisualStateManager )来为一个给定的可视化状态指定控件的外观。控件模版作者也可以通过可视化过渡(VisualTransitions)使用自定义可视化状态之间的过渡。可视化过渡(VisualTransitions)使得空间模版作者能够通过改变单个属性改变的时间和区间对单个过渡(transition)进行微调,甚至对在其他状态中没有提及的属性加上动画效果(animate)。下面的例子使用可视化状态管理器( VisualStateManager )而不是触发器来指定控件外观的改变。
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup.Transitions>
<!--Take one half second to transition to the MouseOver state.-->
<VisualTransition To="MouseOver"
GeneratedDuration="0:0:0.5" />
</VisualStateGroup.Transitions> <VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0"
Storyboard.TargetName="borderColor"
Storyboard.TargetProperty="Color"
To="Cyan"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Duration="0"
Storyboard.TargetName="borderColor"
Storyboard.TargetProperty="Color"
To="Red"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Ellipse>
<Ellipse.Fill>
<SolidColorBrush x:Name="borderColor"
Color="Black"/>
</Ellipse.Fill>
</Ellipse>
<Ellipse x:Name="ButtonShape"
Margin="5"
Fill="{TemplateBinding Background}"/>
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
控件通过使用可视化状态管理器( VisualStateManager )并调用 VisualStateManager.GoToState 来改变可视化状态。当这一切发生时,在可视化状态(VisualState)和可视化过渡(VisualTransition)对象中, 可视化状态管理器( VisualStateManager )正确地停止和开始故事板(storyboards),因此按钮的外观正确地改变可视化状态。为此,这里有一个明确的分工:控件作者指定控件的哪个可视化状态并决定一个控件何时进入每一个可视化状态;模版作者指定这个控件在每个可视化状态中的外观。
然而触发器在WPF中并不是没用了。你可以使用触发器改变控件的外观,这并不对应与一个可视化状态。举个例子,按钮有一个 IsDefault 属性,但是在按钮中没有一个相对应的可视化状态。控件模版作者可能想要指定依赖 IsDefault 的值的按钮外观,这是一个适合用触发器的情景。下面的例子重复了之前的例子,并加入了一个触发器来指定依赖 IsDefault 的值的按钮外观。
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup.Transitions>
<!--Take one half second to transition to the MouseOver state.-->
<VisualTransition To="MouseOver"
GeneratedDuration="0:0:0.5" />
</VisualStateGroup.Transitions> <VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0"
Storyboard.TargetName="borderColor"
Storyboard.TargetProperty="Color"
To="Cyan"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Duration="0"
Storyboard.TargetName="borderColor"
Storyboard.TargetProperty="Color"
To="Red"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Ellipse>
<Ellipse.Fill>
<SolidColorBrush x:Name="borderColor"
Color="Black"/>
</Ellipse.Fill>
</Ellipse>
<Ellipse x:Name="defaultOutline"
Stroke="{TemplateBinding Background}"
StrokeThickness="2"
Margin="2"/>
<Ellipse x:Name="ButtonShape"
Margin="5"
Fill="{TemplateBinding Background}"/>
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsDefault"
Value="False">
<Setter TargetName="defaultOutline"
Property="Stroke"
Value="Transparent"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
按钮中的 IsMouseOver 和 IsPressed 属性依然有效,但是你不应该创建触发器来阻止它们改变按钮的外观。这并不意味这些属性没有用了。这些属性依然可以被应用作者用来在代码中检查控件的可视化状态,甚至当他们使用可视化状态管理器(VisualStateManager)在它们的可视化状态之间过渡时,控件作者应该继续定义用于可视化状态的属性。
【翻译】VSM 和触发器的更多相关文章
- zabbix3.4.7触发器表达式详解
zabbix触发器表达式详解 概述:触发器中的表达式使用很灵活,我们可以创建一个复杂的逻辑测试监控,触发器表达式形式如下: {<server>:<key>.<functi ...
- zabbix-3.4 触发器
3 触发器 概述 触发器是"评估"由项目采集的数据并表示当前系统状况的逻辑表达式. 当监控项用于采集系统的数据时,始终遵循这些数据是非常不切合实际的,因为这些数据始终在等待一个令人 ...
- Bootstrap-17
导入JavaScript插件: 一次性导入:Bootstrap提供了一个单一的文件,这个文件包含了Bootstrap的所有JavaScript插件,即bootstrap.js <!—导入jQue ...
- Blend 2015 教程 (四)控件模板
前一篇讲述了修改ListBox样式的方法,本篇将修改性别显示区域的样式. 1. 选择ListBox控件,编辑ItemTemplate的当前项,选择CheckBox控件,在美工板导航栏中点击CheckB ...
- boostrap插件
第一章:模态弹出框 一.导入JavaScript插件 Bootstrap的JavaScript插件可以单独导入到页面中,也可以一次性导入到页面中.因为在Bootstrap中的JavaScript插件都 ...
- Bootstrap模态弹出框
前面的话 在 Bootstrap 框架中把模态弹出框统一称为 Modal.这种弹出框效果在大多数 Web 网站的交互中都可见.比如点击一个按钮弹出一个框,弹出的框可能是一段文件描述,也可能带有按钮操作 ...
- 自学Zabbix3.6.2-触发器triggers severity严重程度
触发器严重性定义了触发器的重要性. 1. zabbix支持以下触发级别: SEVERITY DEFINITION 颜色 Not classified 未知. 灰色 Information 一般信息. ...
- Bootstrap支持的JavaScript插件
1.导入JavaScript插件 Bootstrap除了包含丰富的Web组件之外,如前面介绍的下拉菜单.按钮组.导航.分页等.他还包括一些JavaScript的插件. Bootstrap的JavaSc ...
- HTML5物理游戏开发 - 越野山地自行车(三)粉碎自行车
自上一章公布到如今已时隔四月,实在对不住大家.让大家久等了~话说不是我不关注我的博客,而是事情一多起来写博客的时间就少了. 待到今日有空了,回头看了看自己曾经写的文章,猛得发现已经四个月不曾写文章了. ...
随机推荐
- 文件上传小技巧/后端处理【以php示例】
引语:在上一篇文章中说到,在页面中可以用隐藏的方式让你的上传页面看起来漂亮.但是这对于性能来说,并没有什么卵用,那么在后台的处理中,难道就没有一些处理技巧么?所谓后台的技巧,应该要包括上传得快一点,上 ...
- Maven系列--"maven-compiler-plugin"的使用
maven是个项目管理工具,如果我们不告诉它我们的代码要使用什么样的jdk版本编译的话,它就会用maven-compiler-plugin默认的jdk版本来进行处理,这样就容易出现版本不匹配的问题,以 ...
- Liferay7 BPM门户开发之30: 通用帮助类Validator、ArrayUtil、StringUtil等使用
废话不多说,直接上代码. 验证类Validator 主要是空验证.数字.格式验证 调用的例子: protected void validateEmailFrom(ActionRequest actio ...
- 10TSQL语言概述-脚本调试-命名规范-天轰穿数据库2014
关键字:sqlserver 数据库脚本 数据库 编码规范大纲:sql概念,TSQL脚本调试,数据库编码规范 优酷超清地址 腾讯超清地址 土豆超清地址
- android: SQLite使用 SQL 操作数据库
虽然 Android 已经给我们提供了很多非常方便的 API 用于操作数据库,不过总会有一些 人不习惯去使用这些辅助性的方法,而是更加青睐于直接使用 SQL 来操作数据库.这种人 一般都是属于 SQL ...
- 携程Android App插件化和动态加载实践
携程Android App的插件化和动态加载框架已上线半年,经历了初期的探索和持续的打磨优化,新框架和工程配置经受住了生产实践的考验.本文将详细介绍Android平台插件式开发和动态加载技术的原理和实 ...
- POI 设置EXCEL单元格格式(日期数字文本等)
HSSFCellStyle style0 = workbook2003.createCellStyle(); style0.setBorderBottom(HSSFCellStyle.BORDER_T ...
- Linux: Set OR Change The Library Path
Linux: Set OR Change The Library Path by NIX CRAFT on APRIL 9, 2010 · 3 COMMENTS· LAST UPDATED AUGUS ...
- 用eclipse建立servlet工程
1.打开eclipse,选择[文件]|[新建]|[项目] 2.选择[Tomcat Project]后单击下一步,输入项目名[TestTomcat],选择下一步,将[Can update contex ...
- 深入分析Java Web技术(2) IO
IO是当今Web面临的主要问题之一,可以说,大部分web应用的瓶颈都是IO的瓶颈. Java的IO类是java.io.它包含有80多个类,分为4大部分: 基于字节操作: InputStream,Out ...