在 WPF 中,Storyboard.Completed 事件不會直接告知是哪個 UI 元素觸發了動畫。但我們可以利用 附加屬性 Storyboard.TargetProperty 來達成需求。
var storyboard = new Storyboard();
var animation = new DoubleAnimation(0, 100, TimeSpan.FromSeconds(1));
Storyboard.SetTarget(animation, myButton);
Storyboard.SetTargetProperty(animation, new PropertyPath(Canvas.LeftProperty));
// 關鍵:將目標元素存入附加屬性
myButton.SetValue(Storyboard.TargetPropertyProperty, myButton);
storyboard.Children.Add(animation);
storyboard.Completed += Storyboard_Completed;
storyboard.Begin();
private void Storyboard_Completed(object sender, EventArgs e)
{
var storyboard = (Storyboard)sender;
// 從動畫的第一個子項取得 Target
var anim = storyboard.Children.FirstOrDefault() as AnimationTimeline;
if (anim != null)
{
var target = Storyboard.GetTarget(anim) as FrameworkElement;
if (target != null)
{
// target 即為執行動畫的 UI 元素
Debug.WriteLine($"動畫完成:{target.Name}");
}
}
}
若需攜帶更多資訊,可定義自訂附加屬性:
public static class AnimationHelper
{
public static readonly DependencyProperty ContextProperty =
DependencyProperty.RegisterAttached("Context", typeof(object), typeof(AnimationHelper));
public static void SetContext(DependencyObject element, object value) => element.SetValue(ContextProperty, value);
public static object GetContext(DependencyObject element) => element.GetValue(ContextProperty);
}
啟動時:AnimationHelper.SetContext(myButton, myButton);
完成時:var ctx = AnimationHelper.GetContext(anim);
雖然 Completed 事件參數不包含發送者元素,但透過 Storyboard.GetTarget 或自訂附加屬性,即可輕鬆在動畫結束時識別並操作對應的 UI 控制項。