计时事件概述

本主题介绍如何使用 TimelineClock 对象上提供的五个计时事件。

先决条件

若要了解本主题,应了解如何创建和使用动画。 若要开始使用动画,请参阅动画概述

在 WPF 中,对属性进行动画处理的方法有很多:

因为可以在标记和代码中使用它们,所以此概述中的示例使用 Storyboard 对象。 但是,所介绍的概念适用于其他对属性进行动画处理的方法。

是什么时钟?

除了描述时间段外,时间线本身并无其他任何作用。 实际工作由时间线的 Clock 对象执行:维护时间线计时相关的运行时状态。 在大多数情况下,比如使用情节提要时,会自动为时间线创建时钟。 还可以使用 CreateClock 方法显式地创建一个 Clock。 有关 Clock 对象的详细信息,请参阅动画和计时系统概述

为什么使用事件?

除了一个例外(对齐到上一时钟周期的查找操作),所有交互式计时操作均为异步操作。 无法准确知道它们何时执行。 当存在其他代码依赖于计时操作时,可能会产生问题。 假设你希望停止对矩形进行动画处理的时间线。 在时间线停止后,更改矩形的颜色。

myStoryboard.Stop(myRectangle);

// This statement might execute
// before the storyboard has stopped.
myRectangle.Fill = Brushes.Blue;
myStoryboard.Stop(myRectangle)

' This statement might execute
' before the storyboard has stopped.
myRectangle.Fill = Brushes.Blue

在上一示例中,第二行代码可能会在情节提要停止前执行。 这是因为停止操作是异步操作。 告知时间线或时钟停止将创建各种“停止请求”,但它仅在计时引擎的下一时钟周期才会处理。

若要在时间线完成后执行命令,请使用计时事件。 在下面的示例中,事件处理程序用于在情节提要停止播放后更改矩形的颜色。

// Register for the CurrentStateInvalidated timing event.
myStoryboard.CurrentStateInvalidated += new EventHandler(myStoryboard_CurrentStateInvalidated);
' Register for the CurrentStateInvalidated timing event.
AddHandler myStoryboard.CurrentStateInvalidated, AddressOf myStoryboard_CurrentStateInvalidated
// Change the rectangle's color after the storyboard stops.
void myStoryboard_CurrentStateInvalidated(object sender, EventArgs e)
{
    Clock myStoryboardClock = (Clock)sender;
    if (myStoryboardClock.CurrentState == ClockState.Stopped)
    {
        myRectangle.Fill = Brushes.Blue;
    }
}
' Change the rectangle's color after the storyboard stops. 
Private Sub myStoryboard_CurrentStateInvalidated(ByVal sender As Object, ByVal e As EventArgs)
    Dim myStoryboardClock As Clock = CType(sender, Clock)
    If myStoryboardClock.CurrentState = ClockState.Stopped Then
        myRectangle.Fill = Brushes.Blue
    End If
End Sub

有关更完整的示例,请参阅在时钟状态发生变化时接收通知

公共活动

TimelineClock 类均提供五个计时事件。 下表列出了这些事件及其触发条件。

事件 触发交互式操作 其他触发器
已完成 跳过以填充 时钟完成。
CurrentGlobalSpeedInvalidated 暂停、恢复、查找、设置速度比、跳过以填充、停止 时钟反转、加速、启动或停止。
CurrentStateInvalidated 开始、跳过以填充、停止 时钟开始、停止或填充。
CurrentTimeInvalidated 开始、查找、跳过以填充、停止 时钟前进。
RemoveRequested 删除

时钟周期和事件合并

在 WPF 中对对象进行动画处理时,计时引擎将管理动画。 计时引擎跟踪时间进度,并计算每个动画的状态。 它一秒内进行多次计算。 这些计算过程称为“时钟周期”。

尽管滴答频率很高,但是在两次滴答之间还是有可能会发生许多事情。 例如,时间线可能会停止、启动、再次停止,在这种情况下其当前状态将更改三次。 从理论上讲,在一个时钟周期内,可以多次引发事件;但是,计时引擎会合并事件,因此每个事件在每个时钟周期内只能引发一次。

注册事件

可以通过两种方法注册计时事件:使用时间线或使用从时间线创建的时钟进行注册。 直接使用时钟注册事件相当简单,不过该方法只能在代码中执行。 可以在标记或代码中使用时间线注册事件。 下一节介绍如何使用时间线注册时钟事件。

使用时间线注册时钟事件

尽管时间线的 CompletedCurrentGlobalSpeedInvalidatedCurrentStateInvalidatedCurrentTimeInvalidatedRemoveRequested 事件似乎与时间线相关联,但注册这些事件实际上会将事件处理程序与为时间线创建的 Clock 相关联。

例如,按时间线注册 Completed 事件时,实际上是在告诉系统针对为时间线创建的每个时钟注册 Completed 事件。 在代码中,为该时间线创建 Clock 之前,必须先注册此事件;否则,你将不会收到通知。 这在 XAML 中会自动发生;在 Clock 创建前,分析器自动注册事件。

另请参阅