C# WPF样式与触发器详解:Style、Setter、Trigger与MultiTrigger

 更新时间:2026年11月10日 09:47:26   作者:沉淀小坤  
界面上有几十个按钮,想让它们字体、颜色都一样,难道一个个写属性,WPF的Style(样式)就像给控件准备的统一制服,定义一次,所有控件都能套用,本文基于我自己的样式触发器学习程序,讲清怎么定义样式、怎么用触发器响应条件,大白话配合可运行代码,适合刚接触 WPF 样式的同学

导语:界面上有几十个按钮,想让它们字体、颜色都一样,难道一个个写属性?WPF 的 Style(样式)就像给控件准备的"统一制服",定义一次,所有控件都能套用。再配上触发器(Trigger),还能做到"鼠标移上去变红、移开恢复"这种条件效果。本文基于我自己的样式触发器学习程序,讲清怎么定义样式、怎么用触发器响应条件,大白话配合可运行代码,适合刚接触 WPF 样式的同学。

一、什么是 Style

Style(样式)是一组属性设置的集合,把控件常用的属性打包定义好,需要的控件直接引用,避免重复写。

打个比方:Style 就像一套"制服模板",规定了字体多大、什么颜色,控件穿上这套制服,就自动拥有这些外观,不用一个个单独打扮。

样式里用 Setter 来设置具体属性,一个 Setter 设置一个属性。

二、定义样式:Style + Setter

在 Window.Resources 资源区定义一个 TextBlock 样式:

<Window.Resources>
    <!-- x:Key:样式的名字,引用时用它
         TargetType:这套样式给哪种控件用 -->
    <Style x:Key="TextBlockStyle" TargetType="{x:Type TextBlock}">
        <!-- Setter:Property 设哪个属性,Value 设成什么值 -->
        <Setter Property="FontFamily" Value="仿宋"/>
        <Setter Property="FontSize" Value="18"/>
        <Setter Property="Foreground" Value="Red"/>
        <Setter Property="FontWeight" Value="Bold"/>
    </Style>
</Window.Resources>

三、应用样式

控件用 Style 属性引用资源区的样式,通过 x:Key 找到它:

<TextBlock Text="引入全局静态的样式" Style="{StaticResource TextBlockStyle}"/>

这个 TextBlock 不用自己写字体颜色,就自动变成仿宋、18 号、红色、加粗。

四、Trigger:属性触发器

光有静态样式还不够,有时希望"满足某个条件时才变样",这就要用触发器。下面给 Border 加触发器:鼠标移上去时变色,移开再变回来。

<Style x:Key="BorderStyle" TargetType="{x:Type Border}">
    <Setter Property="BorderThickness" Value="5"/>
    <!-- Style.Triggers:触发器集合,条件满足时才生效 -->
    <Style.Triggers>
        <!-- 鼠标进入:IsMouseOver 为 True 时 -->
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Background" Value="Red"/>
            <Setter Property="BorderBrush" Value="Aqua"/>
        </Trigger>
        <!-- 鼠标移出:IsMouseOver 为 False 时 -->
        <Trigger Property="IsMouseOver" Value="False">
            <Setter Property="Background" Value="Aqua"/>
            <Setter Property="BorderBrush" Value="Red"/>
        </Trigger>
    </Style.Triggers>
</Style>

触发器的结构记住:Property(看哪个属性)+ Value(等于什么值)+ Setters(满足时改什么)。

五、MultiTrigger:多条件触发器

普通 Trigger 只判断一个条件,MultiTrigger 要多个条件同时满足才触发。比如要求鼠标悬停并且输入框获得焦点,才把背景变红:

<Style x:Key="TextBoxStyle" TargetType="{x:Type TextBox}">
    <Setter Property="BorderThickness" Value="3"/>
    <Style.Triggers>
        <MultiTrigger>
            <!-- 多个条件,必须全部满足 -->
            <MultiTrigger.Conditions>
                <Condition Property="IsMouseOver" Value="true"/>
                <Condition Property="IsFocused" Value="true"/>
            </MultiTrigger.Conditions>
            <!-- 条件都满足时执行的设置 -->
            <MultiTrigger.Setters>
                <Setter Property="Background" Value="Red"/>
            </MultiTrigger.Setters>
        </MultiTrigger>
    </Style.Triggers>
</Style>

Trigger 和 MultiTrigger 的区别:

类型触发条件满足方式
Trigger单个属性条件一个属性等于指定值
MultiTrigger多个属性条件所有条件同时成立

六、StaticResource 与 DynamicResource

应用样式时有两种引用方式,初学者容易混:

  • StaticResource(静态资源):加载时一次性确定,之后不变,适合普通样式。
  • DynamicResource(动态资源):运行时动态查找,资源变化会跟着更新,适合带触发器、会变化的样式。

程序里带触发器的样式用了动态引用:

<!-- 触发器属于条件满足才执行,用 DynamicResource 动态绑定 -->
<Border Width="200" Height="100" Style="{DynamicResource BorderStyle}"/>
<TextBox Width="400" Height="200" Style="{DynamicResource TextBoxStyle}"/>

【插图 1:WPF 样式与触发器的工作机制】

七、常见坑

  1. 样式引用了却不生效。 检查样式的 x:Key 和控件引用的 key 是否一致,TargetType 类型和控件类型是否匹配,类型对不上样式不会生效。
  2. 触发器写了没反应。 确认 Trigger 放在 Style.Triggers 里面,Property 是控件真实存在的属性,Value 值的写法和属性类型对应。
  3. MultiTrigger 不触发。 它要求所有条件同时满足,少一个都不行;先确认每个 Condition 的属性和值都正确,再排查是不是某个条件没达到。
  4. 该用动态资源却用了静态。 带触发器、运行时会变化的样式,用 StaticResource 可能不更新,这类场景改用 DynamicResource。
  5. 样式里直接写控件属性,冲突后不知道听谁的。 控件本地直接写的属性优先级高于样式里的 Setter;如果发现样式没生效,先看控件自己是不是已经写了同名属性。

八、小结

  1. Style 是一组属性设置的集合,用 Setter 设置具体属性,定义一次多处复用。
  2. 控件通过 Style 引用资源区的样式,靠 x:Key 找到。
  3. Trigger 单条件触发,MultiTrigger 多条件同时满足才触发,都放在 Style.Triggers 里。
  4. StaticResource 加载时确定,DynamicResource 运行时动态更新,会变化的样式用动态引用。

以上就是C# WPF样式与触发器详解:Style、Setter、Trigger与MultiTrigger的详细内容,更多关于C# WPF样式与触发器的资料请关注脚本之家其它相关文章!

相关文章

  • 基于C#实现语音预处理

    基于C#实现语音预处理

    无论是在音视频录制系统,还是音视频通话系统或视频会议系统中,对从麦克风采集到的说话的声音数据进行预处理,都是是非常必要的,下面就跟随小编一起来学习一下如何使用C#实现语音预处理吧
    2025-06-06
  • C#使用for循环移除HTML标记

    C#使用for循环移除HTML标记

    大家在项目开发阶段移除文字中的html标记最常用的方法就是使用正则表达式,但是正则表达式不能处理所有的html文档,所以采用迭代方式会更好,下面小编给大家解答下
    2016-08-08
  • C#检测是否有u盘插入的方法

    C#检测是否有u盘插入的方法

    这篇文章主要介绍了C#检测是否有u盘插入的方法,涉及C#操作硬件的相关技巧,需要的朋友可以参考下
    2015-04-04
  • C#泛型概念的简介与泛型的使用

    C#泛型概念的简介与泛型的使用

    今天小编就为大家分享一篇关于C#泛型概念的简介与泛型的使用,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-10-10
  • Unity UGUI的Canvas画布组件使用示例详解

    Unity UGUI的Canvas画布组件使用示例详解

    这篇文章主要介绍了Unity UGUI的Canvas画布组件使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • vs2005中总是保留最近打开的项目和文件的记录

    vs2005中总是保留最近打开的项目和文件的记录

    这篇文章主要介绍了vs2005中总是保留最近打开的项目和文件的记录,需要的朋友可以参考下
    2016-06-06
  • C# Winform 子窗体访问父级窗体的控件和属性

    C# Winform 子窗体访问父级窗体的控件和属性

    本文主要介绍两种子窗体访问父窗体控件和属性的方法,大家可以参考一下,本人比较偏向第二种,把父窗体作为属性传递,一劳永逸,想访问父窗体的什么控件属性都可以。
    2016-05-05
  • C#中实现PriorityQueue优先级队列的代码

    C#中实现PriorityQueue优先级队列的代码

    这篇文章主要介绍了C#中PriorityQueue优先级队列的实现,构造初始化这部分主要介绍关键的字段和方法,比较器的初始化以及堆的初始化,需要的朋友可以参考下
    2021-12-12
  • Unity 如何设定 Animator分割播放

    Unity 如何设定 Animator分割播放

    这篇文章主要介绍了Unity 设定 Animator分割播放的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • 基于C#实现的仿QQ聊天工具的代码详解

    基于C#实现的仿QQ聊天工具的代码详解

    本文介绍了基于C#实现的仿QQ聊天工具的系统架构设计、核心功能模块、数据库设计、通信协议、界面实现、关键技术实现、部署与运维、扩展功能建议以及测试方案,需要的朋友可以参考下
    2026-02-02

最新评论