WPF中有个主题,就是以声明方式扩展代码的功能。当使用样式、资源或数据绑定时,将发现即使不使用代码,也能完成不少工作。

  触发器是另一个实现这种功能的例子。使用触发器,可自动完成简单的样式改变,而这通常需要使用样板事件处理逻辑。例如,当属性发生变化时可以进行响应,并自动调整样式。

  触发器通过Style.Triggers集合链接到样式。每个样式都可以有任意多个触发器,而且每个触发器都是System.Windows.TriggerBase的派生类的实例。下表列出了WPF中的选项。

表 继承自TriggerBase的类

  通过使用FrameworkElement.Triggers集合,可直接为元素应用触发器,而不需要创建样式。但这存在一个相当大的缺陷。这个Triggers集合只支持事件触发器(并非技术上的原因造成了该限制,只是因为WPF团队没时间实现该特性,将来的版本中可能包含该特性)。

一、简单触发器

  可为任何依赖项属性关联简单触发器。例如,可通过响应Control类的IsFocused、IsMouseOver以及IsPressed属性的变化,创建鼠标悬停效果和焦点效果。

  每个简单触发器都制定了正在监视的属性,以及正在等待的属性值。当该属性值出现时,将应用存储在Trigger.Setters集合中的设置器(但不能使用更复杂的触发器逻辑。例如,比较某个值以查看其是否处于某个范围,或执行某种计算等。对于这些情况,最好使用事件处理程序)。

  下面的触发器等待按钮获得键盘焦点,当获取焦点时会将前景色设置为深红色:

  1. <Style x:Key="BigFontButton">
  2. <Style.Setters>
  3. <Setter Property="Control.FontFamily" Value="Times New Roman" />
  4. <Setter Property="Control.FontSize" Value="18" />
  5.  
  6. </Style.Setters>
  7. <Style.Triggers>
  8. <Trigger Property="Control.IsFocused" Value="True">
  9. <Setter Property="Control.Foreground" Value="DarkRed" />
  10. </Trigger>
  11. </Style.Triggers>
  12. </Style>

  触发器的优点是不需要翻转它们而编写任何逻辑。只要停止应用触发器,元素就会恢复到正常外观。在该例中,这意味着只要用户使用Tab键让按钮失去焦点,按钮就会恢复为通常的灰色背景。

  可创建一次应用于同一元素的多个触发器。如果这些触发器设置不同的属性,着鲜红情况就不会出现混乱。然而,如果多个触发器修改同一属性,那么最后的触发器将有效。

  例如,分析下面的触发器,这些触发器根据控件是否焦点、鼠标是否悬停在控件上,以及是否单击了控件,对控件进行修改:

  1. <Style x:Key="BigFontButton">
  2. <Style.Setters>
  3. <Setter Property="Control.FontFamily" Value="Times New Roman" />
  4. <Setter Property="Control.FontSize" Value="18" />
  5.  
  6. </Style.Setters>
  7. <Style.Triggers>
  8. <Trigger Property="Control.IsFocused" Value="True">
  9. <Setter Property="Control.Foreground" Value="DarkRed" />
  10. </Trigger>
  11. <Trigger Property="Control.IsMouseOver" Value="True">
  12. <Setter Property="Control.Foreground" Value="LightYellow" />
  13. <Setter Property="Control.FontWeight" Value="Bold" />
  14. </Trigger>
  15. <Trigger Property="Button.IsPressed" Value="True">
  16. <Setter Property="Control.Foreground" Value="Red" />
  17. </Trigger>
  18. </Style.Triggers>
  19. </Style>

  显然,鼠标可能悬停在当前具有焦点的按钮上。这不会出现问题,因为这两个触发器修改不同的属性。但如果单击按钮,就有两个不同的触发器试图设置前景色。现在,针对Button.IsPressed属性的触发器胜出,因为它是最后一个触发器,这与哪个触发器首先发生并无完全决定了最终效果。

  如果希望创建只有当几个条件都为真时才激活的触发器,可使用MultiTrigger。这种触发器提供了一个Conditions集合,可通过该集合定义一系列属性和值得组合。在下面的示例中,只有按钮具有焦点而且鼠标悬停在该按钮上时,才会应用格式化信息:

  1. <Style x:Key="BigFontButton">
  2. <Style.Setters>
  3. <Setter Property="Control.FontFamily" Value="Times New Roman" />
  4. <Setter Property="Control.FontSize" Value="18" />
  5.  
  6. </Style.Setters>
  7. <Style.Triggers>
  8. <MultiTrigger>
  9. <MultiTrigger.Conditions>
  10. <Condition Property="Control.IsFocused" Value="True"/>
  11. <Condition Property="Control.IsMouseOver" Value="True"/>
  12. </MultiTrigger.Conditions>
  13. <MultiTrigger.Setters>
  14. <Setter Property="Control.Foreground" Value="DarkRed" />
  15. </MultiTrigger.Setters>
  16. </MultiTrigger>
  17. </Style.Triggers>
  18. </Style>

  对于这种情况,不必关心声明条件的顺序,因为在改变背景色之前,这些条件都必须保持为真。

  示例完整的XAML如下所示:

  1. <Window x:Class="Styles.SimpleTriggers"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. Title="SimpleTriggers" Height="300" Width="300">
  5. <Window.Resources>
  6. <Style x:Key="BigFontButton">
  7. <Style.Setters>
  8. <Setter Property="Control.FontFamily" Value="Times New Roman" />
  9. <Setter Property="Control.FontSize" Value="18" />
  10.  
  11. </Style.Setters>
  12. <Style.Triggers>
  13. <MultiTrigger>
  14. <MultiTrigger.Conditions>
  15. <Condition Property="Control.IsFocused" Value="True"/>
  16. <Condition Property="Control.IsMouseOver" Value="True"/>
  17. </MultiTrigger.Conditions>
  18. <MultiTrigger.Setters>
  19. <Setter Property="Control.Foreground" Value="DarkRed" />
  20. </MultiTrigger.Setters>
  21. </MultiTrigger>
  22. </Style.Triggers>
  23. <!--<Style.Triggers>
  24. <Trigger Property="Control.IsFocused" Value="True">
  25. <Setter Property="Control.Foreground" Value="DarkRed" />
  26. </Trigger>
  27. <Trigger Property="Control.IsMouseOver" Value="True">
  28. <Setter Property="Control.Foreground" Value="LightYellow" />
  29. <Setter Property="Control.FontWeight" Value="Bold" />
  30. </Trigger>
  31. <Trigger Property="Button.IsPressed" Value="True">
  32. <Setter Property="Control.Foreground" Value="Red" />
  33. </Trigger>
  34. </Style.Triggers>-->
  35. </Style>
  36. </Window.Resources>
  37.  
  38. <StackPanel Margin="5">
  39. <Button Padding="5" Margin="5"
  40. Style="{StaticResource BigFontButton}"
  41. >A Customized Button</Button>
  42. <TextBlock Margin="5">Normal Content.</TextBlock>
  43. <Button Padding="5" Margin="5"
  44. >A Normal Button</Button>
  45. <TextBlock Margin="5">More normal Content.</TextBlock>
  46. <Button Padding="5" Margin="5"
  47. Style="{StaticResource BigFontButton}"
  48. >Another Customized Button</Button>
  49. </StackPanel>
  50. </Window>

SimpleTriggers

二、事件触发器

  普通触发器等到属性发生变化,而事件触发器等待特定的事件被引发。可能会认为此时应使用设置器来改变元素,但情况并非如此。相反,事件触发器要求用户提供一系列修改空间的动作。这些动作通常被用于动画。

  下面的事件触发器等待MouseEnter事件,然后动态改变按钮的FontSize属性从而形成动画效果,在0.2秒得时间内将字体放大到22个单位:

  1. <Style x:Key="BigFontButton">
  2. <Style.Setters>
  3. <Setter Property="Control.FontFamily" Value="Times New Roman" />
  4. <Setter Property="Control.FontSize" Value="18" />
  5. <Setter Property="Control.FontWeight" Value="Bold" />
  6. </Style.Setters>
  7.  
  8. <Style.Triggers>
  9. <EventTrigger RoutedEvent="Mouse.MouseEnter">
  10. <EventTrigger.Actions>
  11. <BeginStoryboard>
  12. <Storyboard>
  13. <DoubleAnimation
  14. Duration="0:0:0.2"
  15. Storyboard.TargetProperty="FontSize"
  16. To="22" />
  17. </Storyboard>
  18. </BeginStoryboard>
  19. </EventTrigger.Actions>
  20. </EventTrigger>
  21.  
  22. </Style.Triggers>
  23. </Style>

  在XAML中,必须在故事般中定义每个动画,故事板为动画提供了事件线。用户可以在故事板事件内部定义希望使用的一个或多个动画对象。每个动画对象执行本质上相同的任务:在一定时期内修改依赖项属性。

  为了恢复字体大小,样式需要使用响应MouseLeave事件的事件触发器,并在整整两秒的时间内将字体尺寸缩小到原始尺寸。对于这种情况,不需要指明目标字体尺寸——如果没有指明该目标,WPF假定希望使用第一次动画之前按钮原来的字体尺寸:

  1. <Style x:Key="BigFontButton">
  2. <Style.Setters>
  3. <Setter Property="Control.FontFamily" Value="Times New Roman" />
  4. <Setter Property="Control.FontSize" Value="18" />
  5. <Setter Property="Control.FontWeight" Value="Bold" />
  6. </Style.Setters>
  7.  
  8. <Style.Triggers>
  9.  
  10. <EventTrigger RoutedEvent="Mouse.MouseLeave">
  11. <EventTrigger.Actions>
  12. <BeginStoryboard>
  13. <Storyboard>
  14. <DoubleAnimation
  15. Duration="0:0:1"
  16. Storyboard.TargetProperty="FontSize" />
  17. </Storyboard>
  18. </BeginStoryboard>
  19. </EventTrigger.Actions>
  20. </EventTrigger>
  21.  
  22. </Style.Triggers>
  23. </Style>

  示例的完整XAML如下所示:

  1. <Window x:Class="Styles.EventTriggers"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. Title="EventTriggers" Height="300" Width="300">
  5. <Window.Resources>
  6. <Style x:Key="BigFontButton">
  7. <Style.Setters>
  8. <Setter Property="Control.FontFamily" Value="Times New Roman" />
  9. <Setter Property="Control.FontSize" Value="18" />
  10. <Setter Property="Control.FontWeight" Value="Bold" />
  11. </Style.Setters>
  12.  
  13. <Style.Triggers>
  14. <EventTrigger RoutedEvent="Mouse.MouseEnter">
  15. <EventTrigger.Actions>
  16. <BeginStoryboard>
  17. <Storyboard>
  18. <DoubleAnimation
  19. Duration="0:0:0.2"
  20. Storyboard.TargetProperty="FontSize"
  21. To="22" />
  22. </Storyboard>
  23. </BeginStoryboard>
  24. </EventTrigger.Actions>
  25. </EventTrigger>
  26. <EventTrigger RoutedEvent="Mouse.MouseLeave">
  27. <EventTrigger.Actions>
  28. <BeginStoryboard>
  29. <Storyboard>
  30. <DoubleAnimation
  31. Duration="0:0:1"
  32. Storyboard.TargetProperty="FontSize" />
  33. </Storyboard>
  34. </BeginStoryboard>
  35. </EventTrigger.Actions>
  36. </EventTrigger>
  37.  
  38. </Style.Triggers>
  39. </Style>
  40.  
  41. </Window.Resources>
  42.  
  43. <StackPanel Margin="5">
  44. <Button Padding="5" Margin="5"
  45. Style="{StaticResource BigFontButton}"
  46. >A Customized Button</Button>
  47. <TextBlock Margin="5">Normal Content.</TextBlock>
  48. <Button Padding="5" Margin="5"
  49. >A Normal Button</Button>
  50. <TextBlock Margin="5">More normal Content.</TextBlock>
  51. <Button Padding="5" Margin="5"
  52. Style="{StaticResource BigFontButton}"
  53. >Another Customized Button</Button>
  54. </StackPanel>
  55. </Window>

EventTriggers

【WPF学习】第三十七章 触发器的更多相关文章

  1. 【WPF学习】第二十七章 Application类的任务

    上一章介绍了有关WPF应用程序中使用Application对象的方式,接下来看一下如何使用Application对象来处理一些更普通的情况,接下俩介绍如何初始化界面.如何处理命名行参数.如何处理支付窗 ...

  2. 【WPF学习】第十七章 键盘输入

    当用户按下键盘上的一个键时,就会发生一系列事件.下表根据他们的发生顺序列出了这些事件: 表 所有元素的键盘事件(按顺序) 键盘处理永远不会像上面看到的这么简单.一些控件可能会挂起这些事件中的某些事件, ...

  3. 【WPF学习】第十七章 鼠标输入

    鼠标事件执行几个关联的任务.当鼠标移到某个元素上时,可通过最基本的鼠标事件进行响应.这些事件是MouseEnter(当鼠标指针移到元素上时引发该事件)和MouseLeave(当鼠标指针离开元素时引发该 ...

  4. “全栈2019”Java多线程第三十七章:如何让等待的线程无法被中断

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  5. “全栈2019”Java第三十七章:类与字段

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  6. 程序员编程艺术第三十六~三十七章、搜索智能提示suggestion,附近点搜索

    第三十六~三十七章.搜索智能提示suggestion,附近地点搜索 作者:July.致谢:caopengcs.胡果果.时间:二零一三年九月七日. 题记 写博的近三年,整理了太多太多的笔试面试题,如微软 ...

  7. Gradle 1.12用户指南翻译——第三十七章. OSGi 插件

    本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  8. 风炫安全web安全学习第三十七节课 15种上传漏洞讲解(二)

    风炫安全web安全学习第三十七节课 15种上传漏洞讲解(二) 05后缀名黑名单校验之上传.htaccess绕过 还是使用黑名单,禁止上传所有web容器能解析的脚本文件的后缀 $is_upload = ...

  9. [汇编学习笔记][第十七章使用BIOS进行键盘输入和磁盘读写

    第十七章 使用BIOS进行键盘输入和磁盘读写 17.1 int 9 中断例程对键盘输入的处理 17.2 int 16 读取键盘缓存区 mov ah,0 int 16h 结果:(ah)=扫描码,(al) ...

随机推荐

  1. 51nod 1423:最大二“货”

    1423 最大二"货" 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题  收藏  取消关注 白克喜欢找一个序列 ...

  2. mybatis关于级联查询结果集嵌套映射对象非列表的处理问题

    工作中遇到这么一个问题,嵌套查询,返回json的时候,作为属性,deviceFields是一个device中的一个对象属性,在json返回的时候想要得到的应该是deviceFields:{ 具体属性} ...

  3. SpringBoot 系列教程之事务隔离级别知识点小结

    SpringBoot 系列教程之事务隔离级别知识点小结 上一篇博文介绍了声明式事务@Transactional的简单使用姿势,最文章的最后给出了这个注解的多个属性,本文将着重放在事务隔离级别的知识点上 ...

  4. 杂记 -- 关于ref、kepp-alive、nextTick、fetch

    1.ref:定义一个普通的dom节点或一个vue的组件实例对象 定义方法: <div class="page1"> <button @click="li ...

  5. 八十一、SAP中的ALV的简介(ABAP List Viewer)

    一.ALV是SAP中的一个表格,全称为:ABAP List Viewer或者SAP List Viewer,就是可视化表格. ALV是SAP系统中心的列表标准,可以在ABAP程序中进行报表输出.除去列 ...

  6. 六十五、SAP中通过BREAK-POINT下断点,进行调试

    一.代码如下,有2个断点的按钮,可以可以写入BREAK-POINT人工断点 二.运行之后,程序会被断下来, 四个执行按钮,意思分别为:单步进入子程序,单步不进入子程序,返回外面,执行到断点处 三.我们 ...

  7. 三十八、SAP设置默认语言

    一.点击系统->用户参数文件->用户数据 二.设置成需要的语言 三.重新登录,并在登录时选择EN 四.进入界面

  8. Node.js 介绍

    章节 Node.js 介绍 Node.js 入门 Node.js 模块 Node.js HTTP模块 Node.js 文件系统模块 Node.js URL模块 Node.js NPM Node.js ...

  9. python 将数组中取某一值的元素全部替换为其他元素的方法

    这里的问题是在做House Price Prediction的时候遇到的,尝试对GarageArea做log转化,但是由于有些房子没有车库,所以GarageArea = 0,再通过log转化变成-in ...

  10. 漫谈计算机组成原理(七)I/O系统

    本文讲什么? 这个系列的文章其实可以分成两个部分,计算机系统的其他硬件结构和CPU. 而我们今天要讲述的内容,就是其他硬件结构中的最后一个部分--I/O(输入输出)系统. 这篇文章主要讲述的就是I/O ...