在WPF中,Storyboard
可以Storyboard.SkipToFill()
停止,但Completed
事件不会立即触发。正如以下演示代码所示:
public partial class MainWindow : Window
{
private Storyboard _storyboard = new Storyboard();
public MainWindow()
{
InitializeComponent();
InitializeStoryboard();
}
private void InitializeStoryboard()
{
var animation = new DoubleAnimation
{
Duration = TimeSpan.FromSeconds(3),
From = 0,
To = 300
};
Storyboard.SetTarget(animation, MyRectangle);
Storyboard.SetTargetProperty(animation, new PropertyPath(WidthProperty));
_storyboard = new Storyboard();
_storyboard.Children.Add(animation);
_storyboard.Completed += StoryboardOnCompleted;
}
private void StartButton_OnClick(object sender, RoutedEventArgs e)
{
_storyboard.Begin(this, true);
}
private void StopButton_OnClick(object sender, RoutedEventArgs e)
{
_storyboard.SkipToFill(this);
Debug.WriteLine(@"SkipToFill");
}
private void StoryboardOnCompleted(object sender, EventArgs eventArgs)
{
Debug.WriteLine(@"Completed");
}
}
点击StartButton
开始Storyboard
,然后点击StopButton
将其停止。输出将是:
所以,我的问题:如何立即触发Completed
事件?即使输出为:
答案 0 :(得分:0)
您无法控制Storyboard
何时引发Completed
事件,但您可以在事件发生时处理该事件。
因此,您可以将另一个事件处理程序连接到Completed
事件,并在引发Completed
事件后执行您想要的任何操作。
这将按预期顺序打印输出,即事件处理程序将按您注册的顺序调用:
private void StopButton_OnClick(object sender, RoutedEventArgs e)
{
_storyboard.Completed += _storyboard_Completed;
_storyboard.SkipToFill(this);
}
private void _storyboard_Completed(object sender, EventArgs e)
{
Debug.WriteLine(@"SkipToFill");
_storyboard.Completed -= _storyboard_Completed;
}
private void StoryboardOnCompleted(object sender, EventArgs eventArgs)
{
Debug.WriteLine(@"Completed");
}
如果您希望在StopButton_OnClick
方法中实际阻止(异步),直到Completed
被引发,您可以使用SemaphoreSlim
:
private readonly System.Threading.SemaphoreSlim _semaphore = new System.Threading.SemaphoreSlim(0, 1);
private async void StopButton_OnClick(object sender, RoutedEventArgs e)
{
_storyboard.Completed += (ss, ee) => _semaphore.Release();
_storyboard.SkipToFill(this);
await _semaphore.WaitAsync(); //wait here...
Debug.WriteLine(@"SkipToFill");
}
private void StoryboardOnCompleted(object sender, EventArgs eventArgs)
{
Debug.WriteLine(@"Completed");
}
答案 1 :(得分:-1)
SkipToFill
方法计划动画的结尾。我想你可以尝试等待渲染器运行(排序)。我怀疑它会起作用,但无论如何:
_storyboard.SkipToFill(this);
Dispatcher.CurrentDispatcher.Invoke(
new Action(delegate { }), DispatcherPriority.Background);
Debug.WriteLine(@"SkipToFill");