You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF按钮Style Trigger动画问题:同一属性第二个动画不生效

问题描述

通过Style Trigger给按钮添加动画后,同一属性的第二个动画无法生效。具体表现为:鼠标悬停时按钮尺寸能变为120x45,但点击鼠标时无任何反应。

原始XAML代码

<Window x:Class="TestWpf.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestWpf"
        mc:Ignorable="d"
        Title="MainWindow" Height="320" Width="340">
    <Window.Resources>
        <QuadraticEase x:Key="easing" EasingMode="EaseOut"/>
    </Window.Resources>
    <Grid>
        <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
            <Label Name="label"/>
            <Button Content="Hello" Width="100" Height="45">
                <Button.Style>
                    <Style TargetType="Button">
                        <Style.Resources>
                            <Storyboard x:Key="press" x:Name="press">
                                <DoubleAnimation Storyboard.TargetProperty="Width" To="125" Duration="0:0:0.100" EasingFunction="{StaticResource easing}"/>
                                <DoubleAnimation Storyboard.TargetProperty="Height" To="50" Duration="0:0:0.100" EasingFunction="{StaticResource easing}"/>
                            </Storyboard>
                            <Storyboard x:Key="hover" x:Name="hover">
                                <DoubleAnimation Storyboard.TargetProperty="Width" To="120" Duration="0:0:0.200" EasingFunction="{StaticResource easing}"/>
                                <DoubleAnimation Storyboard.TargetProperty="Height" To="45" Duration="0:0:0.200" EasingFunction="{StaticResource easing}"/>
                            </Storyboard>
                            <Storyboard x:Key="leave" x:Name="leave">
                                <DoubleAnimation Storyboard.TargetProperty="Width" To="100" Duration="0:0:0.300" EasingFunction="{StaticResource easing}"/>
                                <DoubleAnimation Storyboard.TargetProperty="Height" To="45" Duration="0:0:0.300" EasingFunction="{StaticResource easing}"/>
                            </Storyboard>
                        </Style.Resources>
                        <Style.Triggers>
                            <Trigger Property="IsPressed" Value="True">
                                <Trigger.EnterActions>
                                    <BeginStoryboard Storyboard="{StaticResource press}"/>
                                </Trigger.EnterActions>
                                <Trigger.ExitActions>
                                    <BeginStoryboard Storyboard="{StaticResource hover}"/>
                                </Trigger.ExitActions>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Trigger.EnterActions>
                                    <BeginStoryboard Storyboard="{StaticResource hover}"/>
                                </Trigger.EnterActions>
                                <Trigger.ExitActions>
                                    <BeginStoryboard Storyboard="{StaticResource leave}"/>
                                </Trigger.ExitActions>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </Button.Style>
            </Button>
        </StackPanel>
    </Grid>
</Window>

需求

  • 按钮默认尺寸为100x45;
  • 鼠标悬停时,动画将按钮尺寸改为120x45(宽度增加20),离开时恢复;
  • 鼠标按下时,动画将尺寸改为125x50(宽高各增加5),松开时恢复。
解决方案

问题原因

鼠标悬停时IsMouseOver触发器的动画已经启动,此时点击按钮触发IsPressed动画时,WPF不会自动终止正在运行的同属性动画,导致新动画无法覆盖生效。此外,虽然IsPressed优先级高于IsMouseOver,但无显式停止操作的话,新动画无法正常启动。

修正方案

  1. 给每个BeginStoryboard添加Name属性,方便在触发器中定位并停止其他动画;
  2. 在IsPressed的EnterActions中先停止hover动画,再启动press动画;在ExitActions中停止press动画,再重启hover动画;
  3. 确保动画结束后保持最终值(默认FillBehavior="HoldEnd",可显式声明)。

修正后的XAML代码

<Window x:Class="TestWpf.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestWpf"
        mc:Ignorable="d"
        Title="MainWindow" Height="320" Width="340">
    <Window.Resources>
        <QuadraticEase x:Key="easing" EasingMode="EaseOut"/>
    </Window.Resources>
    <Grid>
        <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
            <Label Name="label"/>
            <Button Content="Hello" Width="100" Height="45">
                <Button.Style>
                    <Style TargetType="Button">
                        <Style.Resources>
                            <Storyboard x:Key="press">
                                <DoubleAnimation Storyboard.TargetProperty="Width" To="125" Duration="0:0:0.100" EasingFunction="{StaticResource easing}"/>
                                <DoubleAnimation Storyboard.TargetProperty="Height" To="50" Duration="0:0:0.100" EasingFunction="{StaticResource easing}"/>
                            </Storyboard>
                            <Storyboard x:Key="hover">
                                <DoubleAnimation Storyboard.TargetProperty="Width" To="120" Duration="0:0:0.200" EasingFunction="{StaticResource easing}"/>
                                <DoubleAnimation Storyboard.TargetProperty="Height" To="45" Duration="0:0:0.200" EasingFunction="{StaticResource easing}"/>
                            </Storyboard>
                            <Storyboard x:Key="leave">
                                <DoubleAnimation Storyboard.TargetProperty="Width" To="100" Duration="0:0:0.300" EasingFunction="{StaticResource easing}"/>
                                <DoubleAnimation Storyboard.TargetProperty="Height" To="45" Duration="0:0:0.300" EasingFunction="{StaticResource easing}"/>
                            </Storyboard>
                        </Style.Resources>
                        <Style.Triggers>
                            <Trigger Property="IsPressed" Value="True">
                                <Trigger.EnterActions>
                                    <StopStoryboard BeginStoryboardName="hoverStoryboard"/>
                                    <BeginStoryboard x:Name="pressStoryboard" Storyboard="{StaticResource press}"/>
                                </Trigger.EnterActions>
                                <Trigger.ExitActions>
                                    <StopStoryboard BeginStoryboardName="pressStoryboard"/>
                                    <BeginStoryboard x:Name="hoverStoryboardAfterPress" Storyboard="{StaticResource hover}"/>
                                </Trigger.ExitActions>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Trigger.EnterActions>
                                    <BeginStoryboard x:Name="hoverStoryboard" Storyboard="{StaticResource hover}"/>
                                </Trigger.EnterActions>
                                <Trigger.ExitActions>
                                    <StopStoryboard BeginStoryboardName="hoverStoryboard"/>
                                    <StopStoryboard BeginStoryboardName="hoverStoryboardAfterPress"/>
                                    <BeginStoryboard Storyboard="{StaticResource leave}"/>
                                </Trigger.ExitActions>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </Button.Style>
            </Button>
        </StackPanel>
    </Grid>
</Window>

额外说明

  • 使用StopStoryboard终止正在运行的同属性动画,确保新动画能正常启动;
  • 松开按钮时,先停止press动画再启动hover动画,保证回到悬停状态的尺寸;
  • 鼠标离开时,停止所有悬停相关动画,再启动恢复默认尺寸的动画,避免状态冲突。

内容的提问来源于stack exchange,提问作者SlimeNull

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 19:30:50