原文: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 和触发器的更多相关文章

  1. zabbix3.4.7触发器表达式详解

    zabbix触发器表达式详解 概述:触发器中的表达式使用很灵活,我们可以创建一个复杂的逻辑测试监控,触发器表达式形式如下: {<server>:<key>.<functi ...

  2. zabbix-3.4 触发器

    3 触发器 概述 触发器是"评估"由项目采集的数据并表示当前系统状况的逻辑表达式. 当监控项用于采集系统的数据时,始终遵循这些数据是非常不切合实际的,因为这些数据始终在等待一个令人 ...

  3. Bootstrap-17

    导入JavaScript插件: 一次性导入:Bootstrap提供了一个单一的文件,这个文件包含了Bootstrap的所有JavaScript插件,即bootstrap.js <!—导入jQue ...

  4. Blend 2015 教程 (四)控件模板

    前一篇讲述了修改ListBox样式的方法,本篇将修改性别显示区域的样式. 1. 选择ListBox控件,编辑ItemTemplate的当前项,选择CheckBox控件,在美工板导航栏中点击CheckB ...

  5. boostrap插件

    第一章:模态弹出框 一.导入JavaScript插件 Bootstrap的JavaScript插件可以单独导入到页面中,也可以一次性导入到页面中.因为在Bootstrap中的JavaScript插件都 ...

  6. Bootstrap模态弹出框

    前面的话 在 Bootstrap 框架中把模态弹出框统一称为 Modal.这种弹出框效果在大多数 Web 网站的交互中都可见.比如点击一个按钮弹出一个框,弹出的框可能是一段文件描述,也可能带有按钮操作 ...

  7. 自学Zabbix3.6.2-触发器triggers severity严重程度

    触发器严重性定义了触发器的重要性. 1. zabbix支持以下触发级别: SEVERITY DEFINITION 颜色 Not classified 未知. 灰色 Information 一般信息. ...

  8. Bootstrap支持的JavaScript插件

    1.导入JavaScript插件 Bootstrap除了包含丰富的Web组件之外,如前面介绍的下拉菜单.按钮组.导航.分页等.他还包括一些JavaScript的插件. Bootstrap的JavaSc ...

  9. HTML5物理游戏开发 - 越野山地自行车(三)粉碎自行车

    自上一章公布到如今已时隔四月,实在对不住大家.让大家久等了~话说不是我不关注我的博客,而是事情一多起来写博客的时间就少了. 待到今日有空了,回头看了看自己曾经写的文章,猛得发现已经四个月不曾写文章了. ...

随机推荐

  1. 详解Bootstrap列表组组件

    列表组可以用来制作列表清单.垂直导航等效果,也可以配合其他的组件制作出更漂亮的组件,列表组在bootstrap框架中也是一个独立的组件,所以也对应有自己独立源码: LESS:list-group.le ...

  2. SQLite 批量insert - 如何加速SQLite的插入操作

    本人翻译, 原文见: http://tech.vg.no/2011/04/04/speeding-up-sqlite-insert-operations/ 我正在开发一个Android程序, 它使用S ...

  3. solr课程学习系列-solr的概念与结构(1)

    Solr是基于Lucene的采用Java5开发的一个高性能全文搜索服务器.源于lucene,却更比Lucene更为丰富更为强大的查询语言.同时实现了可配置.可扩展并对查询性能进行了优化,并且提供了一个 ...

  4. Install MongoDB driver for PHP on XAMPP for Mac OSX

    试了不少方法,最后还是这个最有效. [转自:http://thatsimplecode.com/install-mongodb-driver-for-php-on-xampp-for-mac-osx] ...

  5. 解决chi_sim.traineddata报read_params_file: parameter not found: allow_blob_division

    在使用语音库时候 遇到报错:allow_blob_division,例如使用chi_sim.traineddata;在chi_sim.traineddata(注意版本)文件目录下,使用命令行执行: c ...

  6. redis的基本使用

    Redis的应用 http://www.redis.cn/commands.html http://www.cnblogs.com/ikodota/archive/2012/03/05/php_red ...

  7. .Net规则引擎介绍 - REngine

    规则引擎 规则引擎由推理引擎发展而来,是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策.接受数据输入,解释业务规则,并根据业务规则做出业务决策 ...

  8. [C#] AY.WPF-图形编程-高中生为起点-研究报告1

    =========================www.ayjs.net独家拥有,未经许可,不许转载,违者追究法律责任 简单的引入:点的平移与转换 System.Window.Point类的 Off ...

  9. quick -- 添加按钮

    cc.ui.UIPushButton.new({ normal = "comm_btnGreenBackBack.png", pressed = "comm_btnGre ...

  10. javamail邮件发送例子

    public class EmailTask{        // Session used by the javamail classes    private Session session;   ...