So far, we worked with styles by setting a static value for a specific property. However, using triggers, you can change the value of a given property, once a certain condition changes. Triggers come in multiple flavors: Property triggers, event triggers and data triggers. They allow you to do stuff that would normally be done in code-behind completely in markup instead, which is all a part of the ongoing process of separating style and code.

Property trigger

The most common trigger is the property trigger, which in markup is simply defined with a <Trigger> element. It watches a specific property on the owner control and when that property has a value that matches the specified value, properties can change. In theory this might sound a bit complicated, but it's actually quite simple once we turn theory into an example:

Download sample

<Window x:Class="WpfTutorialSamples.Styles.StyleTriggersSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="StyleTriggersSample" Height="100" Width="300">
    <Grid>
        <TextBlock Text="Hello, styled world!" FontSize="28" HorizontalAlignment="Center" VerticalAlignment="Center">
            <TextBlock.Style>
                <Style TargetType="TextBlock">
                    <Setter Property="Foreground" Value="Blue"></Setter>
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Foreground" Value="Red" />
                            <Setter Property="TextDecorations" Value="Underline" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </TextBlock.Style>
        </TextBlock>
    </Grid>
</Window>

In this style, we set the Foreground property to blue, to make it look like a hyperlink. We then add a trigger, which listens to theIsMouseOver property - once this property changes to True, we apply two setters: We change the Foreground to red and then we make it underlined. This is a great example on how easy it is to use triggers to apply design changes, completely without any code-behind code.

We define a local style for this specific TextBlock, but as shown in the previous articles, the style could have been globally defined as well, if we wanted it to apply to all TextBlock controls in the application.

Data triggers

Data triggers, represented by the <DataTrigger> element, are used for properties that are not necessarily dependency properties. They work by creating a binding to a regular property, which is then monitored for changes. This also opens up for binding your trigger to a property on a different control. For instance, consider the following example:

Download sample

<Window x:Class="WpfTutorialSamples.Styles.StyleDataTriggerSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="StyleDataTriggerSample" Height="200" Width="200">
    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
        <CheckBox Name="cbSample" Content="Hello, world?" />
        <TextBlock HorizontalAlignment="Center" Margin="0,20,0,0" FontSize="48">
            <TextBlock.Style>
                <Style TargetType="TextBlock">
                    <Setter Property="Text" Value="No" />
                    <Setter Property="Foreground" Value="Red" />
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding ElementName=cbSample, Path=IsChecked}" Value="True">
                            <Setter Property="Text" Value="Yes!" />
                            <Setter Property="Foreground" Value="Green" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </TextBlock.Style>
        </TextBlock>
    </StackPanel>
</Window>

In this example, we have a CheckBox and a TextBlock. Using a DataTrigger, we bind the TextBlock to the IsCheckedproperty of the CheckBox. We then supply a default style, where the text is "No" and the foreground color is red, and then, using a DataTrigger, we supply a style for when the IsChecked property of the CheckBox is changed to True, in which case we make it green with a text saying "Yes!" (as seen on the screenshot).

Event triggers

Event triggers, represented by the <EventTrigger> element, are mostly used to trigger an animation, in response to an event being called. We haven't discussed animations yet, but to demonstrate how an event trigger works, we'll use them anyway. Have a look on the chapter about animations for more details. Here's the example:

Download sample

<Window x:Class="WpfTutorialSamples.Styles.StyleEventTriggerSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="StyleEventTriggerSample" Height="100" Width="300">
    <Grid>
        <TextBlock Name="lblStyled" Text="Hello, styled world!" FontSize="18" HorizontalAlignment="Center" VerticalAlignment="Center">
            <TextBlock.Style>
                <Style TargetType="TextBlock">
                    <Style.Triggers>
                        <EventTrigger RoutedEvent="MouseEnter">
                            <EventTrigger.Actions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation Duration="0:0:0.300" Storyboard.TargetProperty="FontSize" To="28" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </EventTrigger.Actions>
                        </EventTrigger>
                        <EventTrigger RoutedEvent="MouseLeave">
                            <EventTrigger.Actions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation Duration="0:0:0.800" Storyboard.TargetProperty="FontSize" To="18" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </EventTrigger.Actions>
                        </EventTrigger>
                    </Style.Triggers>
                </Style>
            </TextBlock.Style>
        </TextBlock>
    </Grid>
</Window>

The markup might look a bit overwhelming, but if you run this sample and look at the result, you'll see that we've actually accomplished a pretty cool animation, going both ways, in ~20 lines of XAML. As you can see, I use an EventTrigger to subscribe to two events: MouseEnter and MouseLeave. When the mouse enters, I make a smooth and animated transition to a FontSize of 28 pixels in 300 milliseconds. When the mouse leaves, I change the FontSize back to 18 pixels but I do it a bit slower, just because it looks kind of cool.

Summary

WPF styles make it easy to get a consistent look, and with triggers, this look becomes dynamic. Styles are great in your application, but they're even better when used in control templates etc. You can read more about that elsewhere in this tutorial.

In the next article, we'll look at multi triggers, which allow us to apply styles based on multiple properties.

引用自 Trigger, DataTrigger & EventTrigger

参考

Triggers in WPF

WPF MultiTrigger and MultiDataTrigger

DataTemplate.Triggers

[WPF系列]-基础系列 Property Trigger, DataTrigger & EventTrigger的更多相关文章

  1. [WPF系列]-基础系列 TabControl应用

    引言 Tabcontrol控件也是我们在项目中经常用到的一个控件,用它将相关的信息组织在一起分类显示. 简介     ========================================= ...

  2. WPF入门教程系列一——基础

    一. 前言   最近在学习WPF,学习WPF首先上的是微软的MSDN,然后再搜索了一下网络有关WPF的学习资料.为了温故而知新把学习过程记录下来,以备后查.这篇主要讲WPF的开发基础,介绍了如何使用V ...

  3. WPF入门教程系列(二) 深入剖析WPF Binding的使用方法

    WPF入门教程系列(二) 深入剖析WPF Binding的使用方法 同一个对象(特指System.Windows.DependencyObject的子类)的同一种属性(特指DependencyProp ...

  4. WPF入门教程系列(一) 创建你的第一个WPF项目

    WPF入门教程系列(一) 创建你的第一个WPF项目 WPF基础知识 快速学习绝不是从零学起的,良好的基础是快速入手的关键,下面先为大家摞列以下自己总结的学习WPF的几点基础知识: 1) C#基础语法知 ...

  5. C#基础系列——Attribute特性使用

    前言:上篇 C#基础系列——反射笔记 总结了下反射得基础用法,这章我们来看看C#的另一个基础技术——特性. 1.什么是特性:就博主的理解,特性就是在类的类名称.属性.方法等上面加一个标记,使这些类.属 ...

  6. WPF入门教程系列二——Application介绍

    一.Application介绍 WPF和WinForm 很相似, WPF与WinForm一样有一个 Application对象来进行一些全局的行为和操作,并且每个 Domain (应用程序域)中仅且只 ...

  7. C#基础系列:实现自己的ORM(反射以及Attribute在ORM中的应用)

    反射以及Attribute在ORM中的应用 一. 反射什么是反射?简单点吧,反射就是在运行时动态获取对象信息的方法,比如运行时知道对象有哪些属性,方法,委托等等等等.反射有什么用呢?反射不但让你在运行 ...

  8. SpringBoot基础系列-SpringCache使用

    原创文章,转载请标注出处:<SpringBoot基础系列-SpringCache使用> 一.概述 SpringCache本身是一个缓存体系的抽象实现,并没有具体的缓存能力,要使用Sprin ...

  9. SpringBoot基础系列-SpringBoot配置

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9990680.html SpringBoot基础系列-SpringBoot配置 概述 属性 ...

随机推荐

  1. 【转】App开放接口api安全性—Token签名sign的设计与实现

    前言 在app开放接口api的设计中,避免不了的就是安全性问题,因为大多数接口涉及到用户的个人信息以及一些敏感的数据,所以对这些接口需要进行身份的认证,那么这就需要用户提供一些信息,比如用户名密码等, ...

  2. [Q&A] 在证书存储区中找不到清单签名证书

    方案1:右击项目属性->签名->为 ClickOnce 清单签名,将勾掉的选项去掉. 方案2:在签名中创建一个新的签名. 方案3:记事本打开相应的 csproj 文件,调整节点值.< ...

  3. Java之数组篇

    动手动脑,第六次Tutorial--数组 这次的Tutorial讲解了Java中如何进行数组操作,包括数组声明创建使用和赋值运算,写这篇文章的目的就是通过实际运用已达到对数组使用的更加熟练,下面是实践 ...

  4. 手动获取spring的ApplicationContext和bean对象

    WEB项目: 方法1: 1 ApplicationContext ac1 = WebApplicationContextUtils.getRequiredWebApplicationContext(S ...

  5. 软件开发流程 Software development process

    软件开发流程(Software development process)即软件设计思路和方法的一般过程,包括设计软件的功能和实现的算法和方法.软件的总体结构设计和模块设计.编程和调试.程序联调和测试以 ...

  6. SQL Server 2012提供的OFFSET/FETCH NEXT与Row_Number()对比测试(转)

    原文地址:http://www.cnblogs.com/downmoon/archive/2012/04/19/2456451.html 在<SQL Server 2012服务端使用OFFSET ...

  7. Objective-C 排序

    在Objective-C中,排序分为: 1.Foundation框架中的对象排序 2.自定义对象排序 例子:每个学生都有一个成绩score属性,根据成绩score对学生排序 自定义对象 Student ...

  8. K 均值算法(K-means)

    K-means算法是最简单的一种聚类算法.算法的目的是使各个样本与所在类均值的误差平方和达到最小(这也是评价K-means算法最后聚类效果的评价标准) K-means聚类算法的一般步骤: 1. 初始化 ...

  9. iOS多线程之4.GCD简介

    GCD(Grand Central Dispatch)应该是我们开发中最常用到的多线程解决方案,是苹果公司专门为多核的并行运算提出的解决方案,是基于C语言的,提供了很多非常强大的函数. GCD的优势 ...

  10. nodejs的child_process同步异步

    nodejs是一种单线程模型,但是,使用nodejs的child_process模块可以实现多进程任务.利用child_process可以创建子进程,实现子进程和主进程之间的通信. nodejs v0 ...