WinUI 3中如何为执行命令后的按钮添加临时动画?
解决方案
不用从头设计Button样式,直接在C#代码中通过Storyboard实现临时动画,完全保留Button默认行为:
1. 修改ConfirmButton类代码
替换原有的C#实现,通过代码创建动画并自动恢复状态:
using Microsoft.UI; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Media; using Microsoft.UI.Xaml.Media.Animation; namespace BridgeSystems.Framework.WinUI.Controls; public class ConfirmButton : Button { public bool HasBeenExecuted { get => (bool)GetValue(HasBeenExecutedProperty); set => SetValue(HasBeenExecutedProperty, value); } public static readonly DependencyProperty HasBeenExecutedProperty = DependencyProperty.Register(nameof(HasBeenExecuted), typeof(bool), typeof(ConfirmButton), new PropertyMetadata(false, OnHasBeenExecutedChanged)); private static void OnHasBeenExecutedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var button = d as ConfirmButton; if (button == null || !(bool)e.NewValue) return; button.StartConfirmationAnimation(); // 动画结束后重置状态 button.DispatcherQueue.TryEnqueue(async () => { await Task.Delay(2000); // 与动画总时长保持一致 button.HasBeenExecuted = false; }); } private void StartConfirmationAnimation() { // 缓存当前属性值 var originalBackground = Background; var originalForeground = Foreground; var originalFontSize = FontSize; // 快速切换到确认状态的动画 var bgAnim = new ColorAnimation { To = Colors.Green, Duration = TimeSpan.FromMilliseconds(100), FillBehavior = FillBehavior.HoldEnd }; Storyboard.SetTarget(bgAnim, this); Storyboard.SetTargetProperty(bgAnim, "(Button.Background).(SolidColorBrush.Color)"); var fgAnim = new ColorAnimation { To = Colors.White, Duration = TimeSpan.FromMilliseconds(100), FillBehavior = FillBehavior.HoldEnd }; Storyboard.SetTarget(fgAnim, this); Storyboard.SetTargetProperty(fgAnim, "(Button.Foreground).(SolidColorBrush.Color)"); var fontSizeAnim = new DoubleAnimation { To = 20, Duration = TimeSpan.FromMilliseconds(100), FillBehavior = FillBehavior.HoldEnd }; Storyboard.SetTarget(fontSizeAnim, this); Storyboard.SetTargetProperty(fontSizeAnim, "FontSize"); // 延迟恢复到原始状态的动画 var bgResetAnim = new ColorAnimation { To = ((SolidColorBrush)originalBackground).Color, BeginTime = TimeSpan.FromSeconds(1.9), Duration = TimeSpan.FromMilliseconds(100), FillBehavior = FillBehavior.Stop }; Storyboard.SetTarget(bgResetAnim, this); Storyboard.SetTargetProperty(bgResetAnim, "(Button.Background).(SolidColorBrush.Color)"); var fgResetAnim = new ColorAnimation { To = ((SolidColorBrush)originalForeground).Color, BeginTime = TimeSpan.FromSeconds(1.9), Duration = TimeSpan.FromMilliseconds(100), FillBehavior = FillBehavior.Stop }; Storyboard.SetTarget(fgResetAnim, this); Storyboard.SetTargetProperty(fgResetAnim, "(Button.Foreground).(SolidColorBrush.Color)"); var fontSizeResetAnim = new DoubleAnimation { To = originalFontSize, BeginTime = TimeSpan.FromSeconds(1.9), Duration = TimeSpan.FromMilliseconds(100), FillBehavior = FillBehavior.Stop }; Storyboard.SetTarget(fontSizeResetAnim, this); Storyboard.SetTargetProperty(fontSizeResetAnim, "FontSize"); // 组装并启动动画 var storyboard = new Storyboard(); storyboard.Children.Add(bgAnim); storyboard.Children.Add(fgAnim); storyboard.Children.Add(fontSizeAnim); storyboard.Children.Add(bgResetAnim); storyboard.Children.Add(fgResetAnim); storyboard.Children.Add(fontSizeResetAnim); // 保险:动画结束后强制恢复原始属性 storyboard.Completed += (_, __) => { Background = originalBackground; Foreground = originalForeground; FontSize = originalFontSize; }; storyboard.Begin(); } }
2. 使用方式
- 命令执行时,只需将
HasBeenExecuted设为true即可触发动画:// 示例:Command的Executed事件处理 private void MyCustomCommand_Executed(object sender, ExecutedRoutedEventArgs e) { // 执行业务逻辑 confirmButton.HasBeenExecuted = true; } - 也可以通过数据绑定关联ViewModel中的
HasExecuted属性:<local:ConfirmButton Command="{Binding MyCommand}" HasBeenExecuted="{Binding HasExecuted}"/>
关键点说明
- 完全保留Button的默认样式与交互行为(点击、悬停、聚焦等状态不受影响)
- 动画总时长2秒(100ms切换到绿色状态,保持1.8秒,100ms恢复原状),可通过修改
Task.Delay和BeginTime参数调整时长 - 兼容纯色背景场景,若需支持渐变背景,可修改动画目标属性或添加类型判断逻辑
内容的提问来源于stack exchange,提问作者Dabblernl
相关产品推荐
相关产品推荐

