WPF 样式、触发器

样式基础

样式(Style)是组织和重用格式化选项的重要工具。不是使用重复的标记填充XAML,以便设置外边距、内边距、颜色以及字体等细节,而是创建一系列封装所有这些细节的样式,然后再需要之处通过属性来应用样式。

样式是可应用于元素的属性值集合。使用资源的最常见原因之一就是保存样式。

使按钮具有统一格式的实现方式一:资源

<Window.Resources>
        <FontFamily x:Key="ButtonFontFamily">Times New Roman</FontFamily>
        <sys:Double x:Key="ButtonFontSize">18</sys:Double>
        <FontWeight x:Key="ButtonFontWeight">Bold</FontWeight>
    </Window.Resources>
    <Grid Name="gird1" ShowGridLines="True">
        <Button FontFamily="{StaticResource ButtonFontFamily}" FontSize="{StaticResource ButtonFontSize}" FontWeight="{StaticResource ButtonFontWeight}"> 
        </Button>
    </Grid>

这个示例可以正常工作,它将字体细节(所谓的magic number)移出的标记。但也存在两个问题。

  • 除了资源的名称相似之外,没有明确指定三个资源是相关的。这使维护应用程序变得复杂。

  • 需要使用资源的标记非常繁琐。还没有原来不使用资源时简明。

样式为解决这个问题提供了非常好的解决方案。可独立的用户封装所有希望设置的属性的样式。

<Window.Resources>
        <Style x:Key="BigFontButtonStyle">
            <Setter Property="Control.FontFamily" Value="Times New Roman"/>
            <Setter Property="Control.FontSize" Value="18"/>
            <Setter Property="Control.FontWeight" Value="Bold"/>
        </Style>
    </Window.Resources>
    <Grid Name="gird1" ShowGridLines="True">
        <Button Style="{StaticResource BigFontButtonStyle}"> 
        </Button>
    </Grid>

通过样式系统不仅可以创建多组明显相关的属性设置,而且使得应用程序这些设置更加容易,从而精简了标记。

设置属性

每个Style对象都封装了一个Setter对象的集合。每个Setter对象设置元素的单个属性。在某些情况下不能使用简单的特性字符设置属性值。可使用嵌套的元素代替如:

<Setter Property="Control.Background">
        <Setter.Value>
            <ImageBrush  TileMode="Tile" ViewboxUnits="Absolute" Viewport="0 0 32 32" ImageSource="" Opacity="0.3"></ImageBrush>
         </Setter.Value>
</Setter>

创建只应用按钮的样式

<Style x:Key="BigFontButtonStyle" TargetType="Button">
            <Setter Property="FontFamily" Value="Times New Roman"/>
            <Setter Property="FontSize" Value="18"/>
            <Setter Property="FontWeight" Value="Bold"/>
        </Style>

关联事件处理程序

实现元素鼠标悬停效果,需要写后台代码

<Window.Resources>
        <Style x:Key="MouseOverHighlightStyle">
            <EventSetter Event="TextBlock.MouseEnter" Handler="element_MouseEnter"></EventSetter>
            <EventSetter Event="TextBlock.MouseLeave" Handler="element_MouseLeave"></EventSetter>
        </Style>
    </Window.Resources>
    <Grid Name="gird1" ShowGridLines="True">
        <TextBlock Style="{StaticResource MouseOverHighlightStyle}"></TextBlock>
    </Grid>

多层样式

 每个WPF元素一次只能使用一个样式对象,这像是一种限制,但由于属性值的继承和样式继承特性,这种限制实际是不存在的。例如,希望为一组控件使用相同的字体,又不想为每个控件应用相同的样式。对于这种情况,可将他们放置到面板中,并设置容器的样式。只要设置的属性具有属性值继承特性,这些值就会传递到子元素。使用这种模型的属性包括

IsEnabled、IsVisible、Foreground以及所有字体属性。

另外一些情况,可能希望在另一个样式的基础上建立样式,可用BasedOn特性。

<Window.Resources>
        <Style x:Key="BigFontButtonStyle">
            <Setter Property="Control.FontFamily" Value="Times New Roman"/>
            <Setter Property="Control.FontSize" Value="18"/>
            <Setter Property="Control.FontWeight" Value="Bold"/>
        </Style>
        <Style x:Key="NewBigButtonBigFontStyle" BasedOn="{StaticResource BigFontButtonStyle}">
            <Setter Property="Control.Foreground" Value="Red"/>
            <Setter Property="Control.Background" Value="DarkBlue"/>
        </Style>
    </Window.Resources>
    <Grid Name="gird1" ShowGridLines="True">
        <TextBlock Style="{StaticResource NewBigButtonBigFontStyle}">test</TextBlock>
    </Grid>

通过类型自动应用样式

上面都是具有名称的样式,还有一种为特定类型元素自动应用的样式。

<Window.Resources>
        <Style TargetType="Button">
            <Setter Property="Control.FontFamily" Value="Times New Roman"/>
            <Setter Property="Control.FontSize" Value="18"/>
            <Setter Property="Control.FontWeight" Value="Bold"/>
        </Style>
    </Window.Resources>
    <Grid Name="gird1" ShowGridLines="True">
        <Button>one</Button>
        <Button Style="{x:Null}">two</Button>
        <Button>three</Button>
    </Grid>

上面的例子中第二个按钮显示替换了样式,将style设置为null,有效的删除了样式。

触发器

使用触发器可自动完成简单的样式的改变,不需要使用代码,也可以完成不少工作。

触发器通过Style.Trigger集合链接到样式。每个样式可以有任意多个触发器。每个触发器都是System.Windows.TriggerBase的实例。

TriggerBase的子类

简单触发器

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

每个触发器都制定了正在监视的属性以及正在等待的属性值。当属性值出现时,将应用Trigger.Setters集合里的设置器。

<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>
                <Trigger Property="Control.IsFocused" Value="True">
                    <Setter Property="Control.Foreground" Value="DarkRed"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>

触发器的优点是不需要为翻转他们而编写任何代码。

如果希望几个条件都满足时才激活触发器,可使用MultiTrigger

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

 事件触发器

普通触发器等待属性发生变化,而事件触发器等待特定事件被引发。事件触发器要求用户提供一系列修改控件的动作。这些动作常用于动画。

如监听MouseEnter事件,然后动态改变按钮的FontSize属性从而形成动画效果,在0.2秒的时间内容字体放大到22个单位。

<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:3" Storyboard.TargetProperty="FontSize"
                                                 To="50"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
                <EventTrigger RoutedEvent="Mouse.MouseLeave">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Duration="0:0:3" Storyboard.TargetProperty="FontSize"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid Name="gird1" ShowGridLines="True">
        <Button HorizontalAlignment="Center" VerticalAlignment="Center" Style="{StaticResource BigFontButton}">onesfsfsfsfsdfsdf</Button>
    </Grid>

与属性触发器不同如果希望元素返回原始状态,需要反转事件触发器。如上面例子,需要编写MouseLeav事件的触发器。不需要指明字体的大小,默认会恢复成第一次动画之前的字体大小。

 

<think>根据用户的问题,用户希望了解在WPF中通过触发器批量改变样式的方法。结合提供的引用,特别是引用[3]中关于样式的说明,我们可以通过创建样式并添加触发器来实现批量修改。 步骤如下: 1. 定义样式(Style):在资源中定义一个样式,指定目标类型(如Button)和一组Setter(设置默认属性)。 2. 添加触发器(Trigger):在样式中添加触发器触发器可以基于属性值、事件或数据变化来改变控件的样式。 3. 应用样式:将样式应用到多个控件上,这样当触发条件满足时,所有应用该样式的控件都会改变。 例如,我们想要在鼠标悬停时改变多个按钮的背景色和前景色,可以这样实现: 在Window.Resources中定义样式: ```xml <Window.Resources> <Style x:Key="myButtonStyle" TargetType="Button"> <!-- 设置默认属性 --> <Setter Property="Background" Value="LightBlue"/> <Setter Property="Foreground" Value="Black"/> <Setter Property="FontSize" Value="14"/> <Setter Property="Width" Value="100"/> <Setter Property="Height" Value="30"/> <Setter Property="Margin" Value="5"/> <!-- 添加触发器 --> <Style.Triggers> <!-- 鼠标悬停触发器 --> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" Value="DarkBlue"/> <Setter Property="Foreground" Value="White"/> </Trigger> </Style.Triggers> </Style> </Window.Resources> ``` 然后在界面中使用这个样式: ```xml <StackPanel> <Button Style="{StaticResource myButtonStyle}" Content="按钮1"/> <Button Style="{StaticResource myButtonStyle}" Content="按钮2"/> <Button Style="{StaticResource myButtonStyle}" Content="按钮3"/> </StackPanel> ``` 这样,当鼠标悬停到任意一个按钮上时,该按钮的背景色和前景色都会改变。 另外,除了基本触发器(Trigger),还可以使用: - 数据触发器(DataTrigger):当绑定数据满足条件时触发。 - 事件触发器(EventTrigger):当某个事件发生时触发,通常用于动画。 例如,使用DataTrigger: ```xml <Style.Triggers> <DataTrigger Binding="{Binding IsChecked}" Value="True"> <Setter Property="Background" Value="Green"/> </DataTrigger> </Style.Triggers> ``` 注意:如果需要同时修改多个控件,确保这些控件都应用了同一个样式,这样修改样式即可批量修改所有控件的表现。 引用[3]中提到,样式是组织和重用以上细节的重要工具,也是模板和触发器的基础。因此,通过样式触发器,我们可以高效地实现批量修改。 相关问题: 1. 在WPF中,如何创建全局样式以便在整个应用程序中应用? 2. WPF触发器有哪些类型?它们分别适用于什么场景? 3. 如何通过数据绑定和触发器实现动态样式切换?</think>### WPF使用触发器批量修改样式的方法 在WPF中,通过触发器批量修改样式可以通过以下步骤实现: #### 1. **创建基础样式** 在资源中定义基础样式,设置默认属性值: ```xml <Window.Resources> <Style x:Key="ButtonBaseStyle" TargetType="Button"> <Setter Property="Background" Value="LightGray"/> <Setter Property="Foreground" Value="Black"/> <Setter Property="FontSize" Value="14"/> <Setter Property="Padding" Value="10,5"/> </Style> </Window.Resources> ``` #### 2. **添加触发器** 在样式中使用`<Style.Triggers>`批量添加交互效果: ```xml <Style x:Key="ButtonHoverStyle" BasedOn="{StaticResource ButtonBaseStyle}"> <!-- 鼠标悬停触发器 --> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" Value="Blue"/> <Setter Property="Foreground" Value="White"/> <Setter Property="FontWeight" Value="Bold"/> </Trigger> <!-- 禁用状态触发器 --> <Trigger Property="IsEnabled" Value="False"> <Setter Property="Opacity" Value="0.5"/> </Trigger> <!-- 焦点状态触发器 --> <Trigger Property="IsFocused" Value="True"> <Setter Property="BorderBrush" Value="Red"/> <Setter Property="BorderThickness" Value="2"/> </Trigger> </Style.Triggers> </Style> ``` #### 3. **批量应用样式** 在XAML中批量应用样式: ```xml <StackPanel> <Button Style="{StaticResource ButtonHoverStyle}" Content="保存"/> <Button Style="{StaticResource ButtonHoverStyle}" Content="取消"/> <Button Style="{StaticResource ButtonHoverStyle}" Content="删除"/> </StackPanel> ``` #### 4. **高级用法:多条件触发器** 使用`MultiTrigger`实现复杂逻辑: ```xml <Style.Triggers> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsMouseOver" Value="True"/> <Condition Property="IsEnabled" Value="True"/> </MultiTrigger.Conditions> <Setter Property="Background" Value="DarkOrange"/> <Setter Property="Cursor" Value="Hand"/> </MultiTrigger> </Style.Triggers> ``` #### 关键优势: 1. **批量控制**:修改样式资源即可全局更新所有关联控件 2. **状态管理**:通过属性触发器自动响应控件状态变化 3. **代码复用**:避免为每个控件重复编写相同逻辑 4. **维护简便**:所有样式逻辑集中在资源字典中管理 > 提示:使用`BasedOn`属性可继承现有样式(如`ButtonBaseStyle`),实现样式分层和重用[^3]。 --- ### 相关问题 1. 如何在不同窗口间共享相同的样式资源? 2. 使用DataTrigger时如何绑定自定义数据对象? 3. 如何通过EventTrigger实现动画效果的状态切换? 4. 样式继承(`BasedOn`)和样式覆盖的优先级规则是什么?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值