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

WinUI 3中TextBlock动画链实现求助:淡隐→改文本→淡显

WinUI 3 实现TextBlock淡隐-改文本-淡显的动画链方案

你的问题核心是UI线程访问错误和动画未按顺序执行:Task默认在后台线程执行,直接操作UI控件必然触发线程错误;且你未等待动画实际完成就执行后续操作,导致逻辑顺序混乱。以下是两种可行的实现方案:

方案一:利用Storyboard的Completed事件(贴合WPF习惯)

WinUI 3的Storyboard提供了Completed事件,可直接用来构建动画链,和WPF的动画结束事件逻辑一致:

// 初始化淡隐动画(Opacity从1→0)
var fadeOutStoryboard = new Storyboard();
var fadeOutAnimation = new DoubleAnimation
{
    From = 1,
    To = 0,
    Duration = TimeSpan.FromSeconds(0.5) // 自定义动画时长
};
Storyboard.SetTarget(fadeOutAnimation, _TextBlock);
Storyboard.SetTargetProperty(fadeOutAnimation, "Opacity");
fadeOutStoryboard.Children.Add(fadeOutAnimation);

// 初始化淡显动画(Opacity从0→1)
var fadeInStoryboard = new Storyboard();
var fadeInAnimation = new DoubleAnimation
{
    From = 0,
    To = 1,
    Duration = TimeSpan.FromSeconds(0.5)
};
Storyboard.SetTarget(fadeInAnimation, _TextBlock);
Storyboard.SetTargetProperty(fadeInAnimation, "Opacity");
fadeInStoryboard.Children.Add(fadeInAnimation);

// 构建动画链
fadeOutStoryboard.Completed += (s, e) =>
{
    // 淡隐动画结束后修改文本(自动在UI线程执行)
    _TextBlock.Inlines.Clear();
    _TextBlock.Inlines.Add(GetTextInline(phrase));
    // 启动淡显动画
    fadeInStoryboard.Begin();
};

// 启动第一个动画
fadeOutStoryboard.Begin();

方案二:异步等待式实现(简洁异步逻辑)

如果偏好异步编程风格,可通过TaskCompletionSource包装Completed事件,实现await动画完成的逻辑:

// 封装等待Storyboard完成的异步方法
private async Task WaitForStoryboardComplete(Storyboard storyboard)
{
    var tcs = new TaskCompletionSource<bool>();
    void CompletedHandler(object s, object e)
    {
        storyboard.Completed -= CompletedHandler;
        tcs.TrySetResult(true);
    }
    storyboard.Completed += CompletedHandler;
    storyboard.Begin();
    await tcs.Task;
}

// 核心调用逻辑
private async void UpdateTextWithAnimation(string phrase)
{
    // 1. 执行淡隐动画
    var fadeOutAnim = new DoubleAnimation { From = 1, To = 0, Duration = TimeSpan.FromSeconds(0.5) };
    var fadeOutSb = new Storyboard();
    Storyboard.SetTarget(fadeOutAnim, _TextBlock);
    Storyboard.SetTargetProperty(fadeOutAnim, "Opacity");
    fadeOutSb.Children.Add(fadeOutAnim);
    await WaitForStoryboardComplete(fadeOutSb);

    // 2. 修改文本内容
    _TextBlock.Inlines.Clear();
    _TextBlock.Inlines.Add(GetTextInline(phrase));

    // 3. 执行淡显动画
    var fadeInAnim = new DoubleAnimation { From = 0, To = 1, Duration = TimeSpan.FromSeconds(0.5) };
    var fadeInSb = new Storyboard();
    Storyboard.SetTarget(fadeInAnim, _TextBlock);
    Storyboard.SetTargetProperty(fadeInAnim, "Opacity");
    fadeInSb.Children.Add(fadeInAnim);
    await WaitForStoryboardComplete(fadeInSb);
}

// 触发更新示例
// UpdateTextWithAnimation(yourTargetPhrase);

关键注意事项

  • 所有UI操作(动画启动、控件修改)必须在UI线程执行,上述两种方案均天然保证了这一点。
  • 避免用Task.Run或无上下文的Task执行UI操作,必然触发线程错误。
  • 你之前代码中myAnimation2的关键帧逻辑写反(淡显应是0→1而非1→0),已在示例中纠正。

内容的提问来源于stack exchange,提问作者Георгий Попов

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 13:22:47