【WPF学习】第三十七章 触发器

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

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

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

表 继承自TriggerBase的类

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

一、简单触发器

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

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

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

<Style x:Key="BigFontButton">
            <Style.Setters>
                <Setter Property="Control.FontFamily" Value="Times New Roman" />
                <Setter Property="Control.FontSize" Value="18" />

            </Style.Setters>
            <Style.Triggers>
                <Trigger Property="Control.IsFocused" Value="True">
                    <Setter Property="Control.Foreground" Value="DarkRed" />
                </Trigger>
            </Style.Triggers>
        </Style>

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

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

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

<Style x:Key="BigFontButton">
            <Style.Setters>
                <Setter Property="Control.FontFamily" Value="Times New Roman" />
                <Setter Property="Control.FontSize" Value="18" />

            </Style.Setters>
            <Style.Triggers>
                <Trigger Property="Control.IsFocused" Value="True">
                    <Setter Property="Control.Foreground" Value="DarkRed" />
                </Trigger>
                <Trigger Property="Control.IsMouseOver" Value="True">
                    <Setter Property="Control.Foreground" Value="LightYellow" />
                    <Setter Property="Control.FontWeight" Value="Bold" />
                </Trigger>
                <Trigger Property="Button.IsPressed" Value="True">
                    <Setter Property="Control.Foreground" Value="Red" />
                </Trigger>
            </Style.Triggers>
        </Style>

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

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

<Style x:Key="BigFontButton">
            <Style.Setters>
                <Setter Property="Control.FontFamily" Value="Times New Roman" />
                <Setter Property="Control.FontSize" Value="18" />

            </Style.Setters>
            <Style.Triggers>
                <MultiTrigger>
                    <MultiTrigger.Conditions>
                        <Condition Property="Control.IsFocused" Value="True"/>
                        <Condition Property="Control.IsMouseOver" Value="True"/>
                    </MultiTrigger.Conditions>
                    <MultiTrigger.Setters>
                        <Setter Property="Control.Foreground" Value="DarkRed" />
                    </MultiTrigger.Setters>
                </MultiTrigger>
            </Style.Triggers>
        </Style>

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

  示例完整的XAML如下所示:

<Window x:Class="Styles.SimpleTriggers"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="SimpleTriggers" Height="300" Width="300">
    <Window.Resources>
        <Style x:Key="BigFontButton">
            <Style.Setters>
                <Setter Property="Control.FontFamily" Value="Times New Roman" />
                <Setter Property="Control.FontSize" Value="18" />

            </Style.Setters>
            <Style.Triggers>
                <MultiTrigger>
                    <MultiTrigger.Conditions>
                        <Condition Property="Control.IsFocused" Value="True"/>
                        <Condition Property="Control.IsMouseOver" Value="True"/>
                    </MultiTrigger.Conditions>
                    <MultiTrigger.Setters>
                        <Setter Property="Control.Foreground" Value="DarkRed" />
                    </MultiTrigger.Setters>
                </MultiTrigger>
            </Style.Triggers>
            <!--<Style.Triggers>
                <Trigger Property="Control.IsFocused" Value="True">
                    <Setter Property="Control.Foreground" Value="DarkRed" />
                </Trigger>
                <Trigger Property="Control.IsMouseOver" Value="True">
                    <Setter Property="Control.Foreground" Value="LightYellow" />
                    <Setter Property="Control.FontWeight" Value="Bold" />
                </Trigger>
                <Trigger Property="Button.IsPressed" Value="True">
                    <Setter Property="Control.Foreground" Value="Red" />
                </Trigger>
            </Style.Triggers>-->
        </Style>
    </Window.Resources>

    <StackPanel Margin="5">
        <Button Padding="5" Margin="5"
            Style="{StaticResource BigFontButton}"
              >A Customized Button</Button>
        <TextBlock Margin="5">Normal Content.</TextBlock>
        <Button Padding="5" Margin="5"
            >A Normal Button</Button>
        <TextBlock Margin="5">More normal Content.</TextBlock>
        <Button Padding="5" Margin="5"
            Style="{StaticResource BigFontButton}"
              >Another Customized Button</Button>
    </StackPanel>
</Window>

SimpleTriggers

二、事件触发器

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

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

 <Style x:Key="BigFontButton">
            <Style.Setters>
                <Setter Property="Control.FontFamily" Value="Times New Roman" />
                <Setter Property="Control.FontSize" Value="18" />
                <Setter Property="Control.FontWeight" Value="Bold" />
            </Style.Setters>

            <Style.Triggers>
                <EventTrigger RoutedEvent="Mouse.MouseEnter">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation
                  Duration="0:0:0.2"
                  Storyboard.TargetProperty="FontSize"
                  To="22"  />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>

            </Style.Triggers>
        </Style>

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

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

 <Style x:Key="BigFontButton">
            <Style.Setters>
                <Setter Property="Control.FontFamily" Value="Times New Roman" />
                <Setter Property="Control.FontSize" Value="18" />
                <Setter Property="Control.FontWeight" Value="Bold" />
            </Style.Setters>

            <Style.Triggers>

                <EventTrigger RoutedEvent="Mouse.MouseLeave">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation
                  Duration="0:0:1"
                  Storyboard.TargetProperty="FontSize"  />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>

            </Style.Triggers>
        </Style>

  示例的完整XAML如下所示:

<Window x:Class="Styles.EventTriggers"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="EventTriggers" Height="300" Width="300">
    <Window.Resources>
        <Style x:Key="BigFontButton">
            <Style.Setters>
                <Setter Property="Control.FontFamily" Value="Times New Roman" />
                <Setter Property="Control.FontSize" Value="18" />
                <Setter Property="Control.FontWeight" Value="Bold" />
            </Style.Setters>

            <Style.Triggers>
                <EventTrigger RoutedEvent="Mouse.MouseEnter">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation
                  Duration="0:0:0.2"
                  Storyboard.TargetProperty="FontSize"
                  To="22"  />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
                <EventTrigger RoutedEvent="Mouse.MouseLeave">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation
                  Duration="0:0:1"
                  Storyboard.TargetProperty="FontSize"  />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>

            </Style.Triggers>
        </Style>

    </Window.Resources>

    <StackPanel Margin="5">
        <Button Padding="5" Margin="5"
            Style="{StaticResource BigFontButton}"
              >A Customized Button</Button>
        <TextBlock Margin="5">Normal Content.</TextBlock>
        <Button Padding="5" Margin="5"
            >A Normal Button</Button>
        <TextBlock Margin="5">More normal Content.</TextBlock>
        <Button Padding="5" Margin="5"
            Style="{StaticResource BigFontButton}"
              >Another Customized Button</Button>
    </StackPanel>
</Window>

EventTriggers

原文地址:https://www.cnblogs.com/Peter-Luo/p/12293355.html

时间: 2024-10-10 00:44:37

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

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

鼠标事件执行几个关联的任务.当鼠标移到某个元素上时,可通过最基本的鼠标事件进行响应.这些事件是MouseEnter(当鼠标指针移到元素上时引发该事件)和MouseLeave(当鼠标指针离开元素时引发该事件).这两个事件都是直接事件,这意味着他们不使用冒泡和隧道过程,而是源自一个元素并且只被该元素引发.考虑到控件嵌入到WPF窗口的方式,这是合理的. 例如,如果有一个包含按钮的StackPanel面板,并将鼠标指针移到按钮上,那么首先会为这个StackPanel引发MouseEnter事件(当鼠标指

第三十七章

道恒无为,侯王若能守之,万物将自化.化而欲作,吾将镇之以无名之朴.镇之以无名之朴,夫亦将不欲.不欲以静,万物将自定. 第三十七章1 你抱着怎样的心态,世界就怎样回馈你 道恒无为,侯王若能守之,万物将自化. (第三十七章 第1讲) 道”一直是无我利他(即无为)的,领导者如果能按照天之道做事,做到圣人之道,万物会自动跟着你改变,被你感化. 效仿天之道是解开<道德经>秘密的核心.你是什么心态,世界就怎么回馈你,世界会呼应你的心态. 各位朋友大家好,今天我们接着来聊<道德经>. 在讲之前先

【Unity 3D】学习笔记三十七:物理引擎——碰撞与休眠

碰撞与休眠 上一篇笔记说过,当给予游戏对象刚体这个组件以后,那么这个组件将存在碰撞的可能性.一旦刚体开始运动,那么系统方法便会监视刚体的碰撞状态.一般刚体的碰撞分为三种:进入碰撞,碰撞中,和碰撞结束.关于休眠可以理解成为让游戏对象变成静止状态.如果给某个游戏对象休眠的状态,那么这个物体将立马静止,不再运动. 碰撞 首先学习下碰撞几个重要的方法: OnCollisionEnter(  ):刚体开始接触的时候,立即调用. OnCollisionStay(  ):碰撞过程中,每帧都会调用此方法,直到撞

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

本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://github.com/msdx/gradledoc/tree/1.12. 直接浏览双语版的文档请访问: http://gradledoc.qiniudn.com/1.12/userguide/userguide.html. 另外,Android 手机用户可通过我写的一个

【WPF学习】第十一章 理解依赖项属性

依赖项属性是标准.NET属性的全新实现——具有大量新增价值.在WPF的核心特性(如动画.数据绑定以及样式)中需要嵌入依赖项属性.WPF元素提供的大多数属性都是依赖项属性.到目前位置所见到的所有示例都用到了依赖项属性,但你可能还没有意识到这一点.这是因为依赖项属性的用法和普通属性的是相同的. 然而,依赖项属性并非普通属性.可能乐意认为依赖项属性是添加了一套WPF功能的常规属性(采用典型的.NET方式进行定义).从概念上讲,依赖项属性确实以这种方式工作,但它们的背后的实现方式并非如此.原因十分简单:

【WPF学习】第十三章 理解路由事件

每个.NET开发人员都熟悉“事件”的思想——当有意义的事情发生时,由对象(如WPF元素)发送的用于通知代码的消息.WPF通过事件路由(event routing)的概念增强了.NET事件模型.事件路由允许源自某个元素的事件由另一个元素引发.例如,使用事件路由,来自工具栏按钮的单击事件可在被代码处理之前上传到工具栏,然后上传到包含工具栏的窗口. 事件路由为在最合适的位置编写紧凑的.组织良好的用于处理事件的代码提供了灵活性.要使用WPF内容模型,事件路由也是必需的,内容模型允许使用许多不同的元素构建

WPF学习(三)--Menu和TabControl控件介绍

Menu Menu提供了菜单栏方式的多级菜单的管理和操作: 这里对Menu的样式不做任何的定制和管理 下面来对Menu进行测试: 将Menu添加到页面中 运行后,效果如下: 这里没有考虑界面效果和样式. TabControl TabControl是非常常见和有用的控件, 数据控件 DataGrid DataGrid 是WPF中最常用的列表数据显示控件,该控件功能强大,并且拥有强大的可定制性 上面给出的是dataGrid的基本属性,下面我们通过设置样式,来设置下DataGrid的基本样式: 关于触

WPF学习(三) - 依赖属性和附加属性

学习WPF时,我在看一本叫做“深入浅出WPF”的书.整整20页都在讲依赖性性和附加属性,反复看了几遍居然还是不懂,真是郁闷. 上一篇中WPF绑定的例子,其实已经用到了依赖属性. // 作为被绑定的目标类,必须从DependencyObject派生 // 这样定义的类才能满足SetBinding方法的第一个参数的类型要求 // 还要额外定义一个依赖属性,用来满足SetBinding方法的第二个参数要求 // 用DependencyObject派生方法GetValue和SetValue,控制属性的存

【WPF学习】第四章 加载和编译XAML

前面已经介绍过,尽管XAML和WPF这两种技术具有相互补充的作用,但他们也是相互独立的.因此,完全可以创建不使用XAML和WPF应用程序. 总之,可使用三种不同的编码方式来创建WPF应用程序: 只使用代码.这是在Visual Studio中为Windows窗体应用程序使用的传统方法.它通过代码语句生成用户界面. 使用代码和未经编译的标记(XAML).这种具体方式对于某些特殊情况是很有意义的,例如创建高度动态化的用户界面.这种方式在运行时使用System.Windows.Markup名称空间中的X