演示图板概述Storyboards Overview

本主题演示如何使用 Storyboard 对象来组织和应用动画。This topic shows how to use Storyboard objects to organize and apply animations. 它介绍了如何以交互方式操作 Storyboard 对象并描述间接属性目标语法。It describes how to interactively manipulate Storyboard objects and describes indirect property targeting syntax.

必备条件Prerequisites

若要了解本主题,应熟悉不同的动画类型及其基本功能。To understand this topic, you should be familiar with the different animation types and their basic features. 有关动画的简介,请参阅动画概述For an introduction to animation, see the Animation Overview. 还应了解如何使用附加属性。You should also know how to use attached properties. 有关附加属性的详细信息,请参阅附加属性概述For more information about attached properties, see the Attached Properties Overview.

什么是情节提要What Is a Storyboard

动画并非唯一有用的时间线类型。Animations are not the only useful type of timeline. 还提供了其他时间线类来帮助组织时间线集,并将时间线应用于属性。Other timeline classes are provided to help you organize sets of timelines, and to apply timelines to properties. 容器时间线派生自 TimelineGroup 类,并包括 ParallelTimelineStoryboardContainer timelines derive from the TimelineGroup class, and include ParallelTimeline and Storyboard.

Storyboard是一种为其所包含的时间线提供目标信息的容器时间线。A Storyboard is a type of container timeline that provides targeting information for the timelines it contains. 情节提要可以包含任何类型 Timeline ,包括其他容器时间线和动画。A Storyboard can contain any type of Timeline, including other container timelines and animations. Storyboard 使用对象,您可以将影响各种对象和属性的时间线合并为单个时间线树,以便于组织和控制复杂的计时行为。Storyboard objects enable you to combine timelines that affect a variety of objects and properties into a single timeline tree, making it easy to organize and control complex timing behaviors. 例如,假设需要一个执行以下三个操作的按钮。For example, suppose you want a button that does these three things.

  • 当用户选择该按钮时,按钮增大并更改颜色。Grow and change color when the user selects the button.

  • 当用户单击该按钮时,按钮缩小并恢复其原始大小。Shrink away and then grow back to its original size when clicked.

  • 当该按钮变为禁用状态时,按钮缩小且不透明度缩减到 50%。Shrink and fade to 50 percent opacity when it becomes disabled.

在此情况下,有多组动画适用于同一对象,并且需要根据按钮的状态在不同的时间播放它们。In this case, you have multiple sets of animations that apply to the same object, and you want to play at different times, dependent on the state of the button. Storyboard 使用对象可以组织动画并将它们按组应用到一个或多个对象。Storyboard objects enable you to organize animations and apply them in groups to one or more objects.

在哪里可以使用情节提要Where Can You Use a Storyboard

Storyboard可用于对动画处理类的依赖属性进行动画处理 (有关如何动画处理类的详细信息,请参阅动画概述) 。A Storyboard can be used to animate dependency properties of animatable classes (for more information about what makes a class animatable, see the Animation Overview). 但是,因为情节提要是一个框架级别功能,所以该对象必须属于 NameScope FrameworkElement 或的 FrameworkContentElementHowever, because storyboarding is a framework-level feature, the object must belong to the NameScope of a FrameworkElement or a FrameworkContentElement.

例如,你可以使用 Storyboard 来执行以下操作:For example, you could use a Storyboard to do the following:

但是,您不能使用 Storyboard 对未向或注册其名称的进行动画处理,也不能使用来 SolidColorBrush FrameworkElement FrameworkContentElement 设置或的属性 FrameworkElement FrameworkContentElementHowever, you could not use a Storyboard to animate a SolidColorBrush that did not register its name with a FrameworkElement or FrameworkContentElement, or was not used to set a property of a FrameworkElement or FrameworkContentElement.

如何使用情节提要应用动画How to Apply Animations with a Storyboard

若要使用 Storyboard 来组织和应用动画,请将动画添加为的子时间线 StoryboardTo use a Storyboard to organize and apply animations, you add the animations as child timelines of the Storyboard. Storyboard类提供 Storyboard.TargetName Storyboard.TargetProperty 属性和附加属性。The Storyboard class provides the Storyboard.TargetName and Storyboard.TargetProperty attached properties. 可以在动画上设置这些属性以指定其目标对象和属性。You set these properties on an animation to specify its target object and property.

若要将动画应用于其目标,请 Storyboard 使用触发器操作或方法开始。To apply animations to their targets, you begin the Storyboard using a trigger action or a method. 在中 XAMLXAML ,可以使用 BeginStoryboard 具有 EventTrigger 、或的对象 Trigger DataTriggerIn XAMLXAML, you use a BeginStoryboard object with an EventTrigger, Trigger, or DataTrigger. 在代码中,还可以使用 Begin 方法。In code, you can also use the Begin method.

下表显示支持每个开始技术的不同位置 Storyboard :每个实例、样式、控件模板和数据模板。The following table shows the different places where each Storyboard begin technique is supported: per-instance, style, control template, and data template. “基于实例”是指直接将动画或情节提要应用于对象实例(而不是在样式、控件模板或数据模板中应用)的技术。"Per-Instance" refers to the technique of applying an animation or storyboard directly to instances of an object, rather than in a style, control template, or data template.

情节提要开始时使用…Storyboard is begun using… 基于实例Per-instance StyleStyle 控件模板Control template 数据模板Data template 示例Example
BeginStoryboardEventTriggerBeginStoryboard and an EventTrigger Yes Yes Yes Yes 使用情节提要对属性进行动画处理Animate a Property by Using a Storyboard
BeginStoryboard 和属性 TriggerBeginStoryboard and a property Trigger No Yes Yes Yes 在属性值更改时触发动画Trigger an Animation When a Property Value Changes
BeginStoryboard 和属性 MultiTriggerBeginStoryboard and a property MultiTrigger No Yes Yes Yes MultiTrigger 类示例MultiTrigger class example
BeginStoryboardDataTriggerBeginStoryboard and a DataTrigger No Yes Yes Yes 如何:在数据更改时触发动画How to: Trigger an Animation When Data Changes
BeginStoryboardMultiDataTriggerBeginStoryboard and a MultiDataTrigger No Yes Yes Yes MultiDataTrigger 类示例MultiDataTrigger class example
Begin 方法Begin method Yes No No No 使用情节提要对属性进行动画处理Animate a Property by Using a Storyboard

下面的示例使用 Storyboard 对某个元素的 Width RectangleColor SolidColorBrush 用于绘制该 Rectangle 的的的。The following example uses a Storyboard to animate the Width of a Rectangle element and the Color of a SolidColorBrush used to paint that Rectangle.

<!-- This example shows how to animate with a storyboard.-->
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="Microsoft.Samples.Animation.StoryboardsExample" 
  WindowTitle="Storyboards Example">
  <StackPanel Margin="20">
    
    <Rectangle Name="MyRectangle"
      Width="100"
      Height="100">
      <Rectangle.Fill>
        <SolidColorBrush x:Name="MySolidColorBrush" Color="Blue" />
      </Rectangle.Fill>
      <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Rectangle.MouseEnter">
          <BeginStoryboard>
            <Storyboard>
              <DoubleAnimation 
                Storyboard.TargetName="MyRectangle"
                Storyboard.TargetProperty="Width"
                From="100" To="200" Duration="0:0:1" />
              
              <ColorAnimation 
                Storyboard.TargetName="MySolidColorBrush"
                Storyboard.TargetProperty="Color"
                From="Blue" To="Red" Duration="0:0:1" />  
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Rectangle.Triggers>
    </Rectangle> 
  </StackPanel>
</Page>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Data;
using System.Windows.Shapes;
using System.Windows.Input;

namespace Microsoft.Samples.Animation
{
    public class StoryboardsExample : Page
    {
        public StoryboardsExample()
        {
            this.WindowTitle = "Storyboards Example";
            StackPanel myStackPanel = new StackPanel();
            myStackPanel.Margin = new Thickness(20);

            Rectangle myRectangle = new Rectangle();
            myRectangle.Name = "MyRectangle";

            // Create a name scope for the page.
            NameScope.SetNameScope(this, new NameScope());

            this.RegisterName(myRectangle.Name, myRectangle);
            myRectangle.Width = 100;
            myRectangle.Height = 100;
            SolidColorBrush mySolidColorBrush = new SolidColorBrush(Colors.Blue);
            this.RegisterName("MySolidColorBrush", mySolidColorBrush);
            myRectangle.Fill = mySolidColorBrush;

            DoubleAnimation myDoubleAnimation = new DoubleAnimation();
            myDoubleAnimation.From = 100;
            myDoubleAnimation.To = 200;
            myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
            Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
            Storyboard.SetTargetProperty(myDoubleAnimation,
                new PropertyPath(Rectangle.WidthProperty));

            ColorAnimation myColorAnimation = new ColorAnimation();
            myColorAnimation.From = Colors.Blue;
            myColorAnimation.To = Colors.Red;
            myColorAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
            Storyboard.SetTargetName(myColorAnimation, "MySolidColorBrush");
            Storyboard.SetTargetProperty(myColorAnimation,
                new PropertyPath(SolidColorBrush.ColorProperty));
            Storyboard myStoryboard = new Storyboard();
            myStoryboard.Children.Add(myDoubleAnimation);
            myStoryboard.Children.Add(myColorAnimation);

            myRectangle.MouseEnter += delegate(object sender, MouseEventArgs e)
            {
                myStoryboard.Begin(this);
            };

            myStackPanel.Children.Add(myRectangle);
            this.Content = myStackPanel;
        }
    }
}

以下部分 TargetName TargetProperty 更详细地介绍了和附加属性。The following sections describe the TargetName and TargetProperty attached properties in more detail.

以框架元素、框架内容元素和 Freezable 元素为目标Targeting Framework Elements, Framework Content Elements, and Freezables

上一节提到过,对于要查找其目标的动画,必须知道目标的名称和要进行动画处理的属性。The previous section mentioned that, for an animation to find its target, it must know the target's name and the property to animate. 指定要进行动画处理的属性是一种直接的方式:只需 TargetProperty 用要进行动画处理的属性的名称进行设置。Specifying the property to animate is straight forward: simply set TargetProperty with the name of the property to animate. 通过设置动画的属性,指定要为其设置动画的属性的对象的名称 Storyboard.TargetNameYou specify the name of the object whose property you want to animate by setting the Storyboard.TargetName property on the animation.

注意

尽管可以使用 Target 属性直接绑定到对象作为的替代项 TargetName ,但它不能序列化。While you can use the Target property to bind directly to an object as an alternative to TargetName, it isn't serializable. 不保证 Target 可以在 XAML 中正确地引用该对象。There is no guaranteed that the Target object can be correctly referenced in XAML.

要使 TargetName 属性正常工作,目标对象必须具有名称。For the TargetName property to work, the targeted object must have a name. FrameworkElement 或在中分配名称与 FrameworkContentElementXAMLXAML 对象分配名称不同 FreezableAssigning a name to a FrameworkElement or a FrameworkContentElement in XAMLXAML is different than assigning a name to a Freezable object.

框架元素是从类继承的类 FrameworkElementFramework elements are those classes that inherit from the FrameworkElement class. 框架元素的示例包括 WindowDockPanelButtonRectangleExamples of framework elements include Window, DockPanel, Button, and Rectangle. 实质上,所有窗口、面板和控件都是元素。Essentially all windows, panels, and controls are elements. 框架内容元素是从类继承的类 FrameworkContentElementFramework content elements are those classes that inherit from the FrameworkContentElement class. 框架内容元素的示例包括 FlowDocumentParagraphExamples of framework content elements include FlowDocument and Paragraph. 如果不确定某个类型是框架元素还是框架内容元素,请查看它是否具有 Name 属性。If you're not sure whether a type is a framework element or a framework content element, check to see whether it has a Name property. 如果具有 Name 属性,则可能是框架元素或框架内容元素。If it does, it's probably a framework element or a framework content element. 若要进一步确定,请检查其类型页面的“继承性分层”部分。To be sure, check the Inheritance Hierarchy section of its type page.

若要在中启用框架元素或框架内容元素的目标 XAMLXAML ,请设置其 Name 属性。To enable the targeting of a framework element or a framework content element in XAMLXAML, you set its Name property. 在代码中,还需要使用 RegisterName 方法来向已为其创建的元素注册元素的名称 NameScopeIn code, you also need to use the RegisterName method to register the element's name with the element for which you've created a NameScope.

下面的示例摘自前面的示例,它为指定了名称 MyRectangle a Rectangle FrameworkElementThe following example, taken from the preceding example, assigns the name MyRectangle a Rectangle, a type of FrameworkElement.

<Rectangle Name="MyRectangle"
  Width="100"
  Height="100">
Rectangle myRectangle = new Rectangle();
myRectangle.Name = "MyRectangle";

// Create a name scope for the page.
NameScope.SetNameScope(this, new NameScope());

this.RegisterName(myRectangle.Name, myRectangle);

在该元素具有名称后,可以对其属性进行动画处理。After it has a name, you can animate a property of that element.

<DoubleAnimation 
  Storyboard.TargetName="MyRectangle"
  Storyboard.TargetProperty="Width"
  From="100" To="200" Duration="0:0:1" />
Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
Storyboard.SetTargetProperty(myDoubleAnimation,
    new PropertyPath(Rectangle.WidthProperty));

Freezable 类型是从类继承的类 FreezableFreezable types are those classes that inherit from the Freezable class. 的示例 Freezable 包括 SolidColorBrushRotateTransformGradientStopExamples of Freezable include SolidColorBrush, RotateTransform, and GradientStop.

若要 Freezable 在中启用动画的目标 XAMLXAML ,可以使用 x:Name 指令 为其分配名称。To enable the targeting of a Freezable by an animation in XAMLXAML, you use the x:Name Directive to assign it a name. 在代码中,使用 RegisterName 方法将其名称注册到已为其创建的元素 NameScopeIn code, you use the RegisterName method to register its name with the element for which you've created a NameScope.

下面的示例将一个名称分配给 Freezable 对象。The following example assigns a name to a Freezable object.

<SolidColorBrush x:Name="MySolidColorBrush" Color="Blue" />
SolidColorBrush mySolidColorBrush = new SolidColorBrush(Colors.Blue);
this.RegisterName("MySolidColorBrush", mySolidColorBrush);

然后动画便可以该对象为目标。The object can then be targeted by an animation.

<ColorAnimation 
  Storyboard.TargetName="MySolidColorBrush"
  Storyboard.TargetProperty="Color"
  From="Blue" To="Red" Duration="0:0:1" />  
Storyboard.SetTargetName(myColorAnimation, "MySolidColorBrush");
Storyboard.SetTargetProperty(myColorAnimation,
    new PropertyPath(SolidColorBrush.ColorProperty));

Storyboard 对象使用名称范围来解析 TargetName 属性。Storyboard objects use name scopes to resolve the TargetName property. 有关 WPF 名称范围的详细信息,请参阅 WPF XAML 名称范围For more information about WPF name scopes, see WPF XAML Namescopes. 如果 TargetName 省略该属性,则动画将以定义它的元素为目标; 对于样式为样式的元素。If the TargetName property is omitted, the animation targets the element on which it is defined, or, in the case of styles, the styled element.

有时,不能将名称分配给 Freezable 对象。Sometimes a name can't be assigned to a Freezable object. 例如,如果 Freezable 声明为资源或用于设置样式中的属性值,则不能为其指定名称。For example, if a Freezable is declared as a resource or used to set a property value in a style, it can't be given a name. 由于该对象没有名称,因此不能直接以它为目标,但可以间接以它为目标。Because it doesn't have a name, it can't be targeted directly—but it can be targeted indirectly. 下面几节描述如何使用间接目标。The following sections describe how to use indirect targeting.

间接目标Indirect Targeting

有时 Freezable 动画无法直接定位,例如,当 Freezable 声明为资源或用于设置样式中的属性值时。There are times a Freezable can't be targeted directly by an animation, such as when the Freezable is declared as a resource or used to set a property value in a style. 在这些情况下,即使您不能直接将其作为目标,您仍然可以对对象进行动画处理 FreezableIn these cases, even though you can't target it directly, you can still animate the Freezable object. 不是将属性设置为的 TargetName 名称,而是 Freezable 为其提供 "所属" 的元素的名称 FreezableInstead of setting the TargetName property with the name of the Freezable, you give it the name of the element to which the Freezable "belongs." 例如, SolidColorBrush 用于设置 Fill 矩形元素的属于该矩形的。For example, a SolidColorBrush used to set the Fill of a rectangle element belongs to that rectangle. 若要对画笔进行动画处理,请设置动画的 TargetProperty 属性链,该链以 Freezable 用于设置的属性和结束于要 Freezable 进行动画处理的属性结束。To animate the brush, you would set the animation's TargetProperty with a chain of properties that starts at the property of the framework element or framework content element the Freezable was used to set and ends with the Freezable property to animate.

<ColorAnimation 
  Storyboard.TargetName="Rectangle01"
  Storyboard.TargetProperty="Fill.Color"
  From="Blue" To="AliceBlue" Duration="0:0:1" />
DependencyProperty[] propertyChain =
    new DependencyProperty[]
        {Rectangle.FillProperty, SolidColorBrush.ColorProperty};
string thePath = "(0).(1)";
PropertyPath myPropertyPath = new PropertyPath(thePath, propertyChain);
Storyboard.SetTargetProperty(myColorAnimation, myPropertyPath);

请注意,如果 Freezable 冻结,将进行克隆,并对该克隆进行动画处理。Note that, if the Freezable is frozen, a clone will be made, and that clone will be animated. 发生这种情况时,原始对象的 HasAnimatedProperties 属性将继续返回 false ,因为原始对象并未进行动画处理。When this happens, the original object's HasAnimatedProperties property continues to return false, because the original object is not actually animated. 有关克隆的详细信息,请参阅 " 冻结对象概述"。For more information about cloning, see the Freezable Objects Overview.

另请注意,当使用间接属性目标时,可能会以不存在的对象为目标。Also note that, when using indirect property targeting, it's possible to target objects that don't exist. 例如,你可能会假设使用 Background 设置了特定按钮的, SolidColorBrush 并尝试对其颜色进行动画处理(事实上, LinearGradientBrush 使用来设置按钮的背景)。For example, you might assume that the Background of a particular button was set with a SolidColorBrush and try to animate its Color, when in fact a LinearGradientBrush was used to set the button's Background. 在这些情况下,不会引发异常;由于不 LinearGradientBrush 会对属性的更改做出反应,动画无法获得可见效果 ColorIn these cases, no exception is thrown; the animation fails to have a visible effect because LinearGradientBrush does not react to changes to the Color property.

下面几节详细介绍间接属性目标语法。The following sections describe indirect property targeting syntax in more detail.

在 XAML 中间接以 Freezable 的属性为目标Indirectly Targeting a Property of a Freezable in XAML

若要以可冻结的属性为目标 XAMLXAML ,请使用以下语法。To target a property of a freezable in XAMLXAML, use the following syntax.

ElementPropertyName . FreezablePropertyNameElementPropertyName . FreezablePropertyName

WhereWhere

下面的代码演示如何对 Color SolidColorBrush 用于设置矩形元素的的的进行动画处理 FillThe following code shows how to animate the Color of a SolidColorBrush used to set the Fill of a rectangle element.

<Rectangle
  Name="Rectangle01"
  Height="100"
  Width="100"
  Fill="{StaticResource MySolidColorBrushResource}">
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.MouseEnter">
      <BeginStoryboard>
        <Storyboard>
          <ColorAnimation 
            Storyboard.TargetName="Rectangle01"
            Storyboard.TargetProperty="Fill.Color"
            From="Blue" To="AliceBlue" Duration="0:0:1" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers>
</Rectangle>

有时,需要以集合或数组中包含的 Freezable 为目标。Sometimes you need to target a freezable contained in a collection or array.

若要以集合中包含的 Freezable 为目标,可以使用以下路径语法。To target a freezable contained in a collection, you use the following path syntax.

ElementPropertyName .Children[ CollectionIndex ]. FreezablePropertyNameElementPropertyName .Children[ CollectionIndex ]. FreezablePropertyName

其中, CollectionIndex 是对象在其数组或集合中的索引。Where CollectionIndex is the index of the object in its array or collection.

例如,假设某个矩形有一个 TransformGroup 应用于其属性的资源 RenderTransform ,并且您想要对它所包含的其中一个转换进行动画处理。For example, suppose that a rectangle has a TransformGroup resource applied to its RenderTransform property, and you want to animate one of the transforms it contains.

<TransformGroup x:Key="MyTransformGroupResource"
  x:Shared="False">
  <ScaleTransform />
  <RotateTransform />
</TransformGroup>

下面的代码演示如何对 Angle RotateTransform 上一个示例中所示的的属性进行动画处理。The following code shows how to animate the Angle property of the RotateTransform shown in the previous example.

<Rectangle
  Name="Rectangle02"
  Height="100"
  Width="100"
  Fill="Blue"
  RenderTransform="{StaticResource MyTransformGroupResource}">
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.MouseEnter">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimation 
            Storyboard.TargetName="Rectangle02"
            Storyboard.TargetProperty="RenderTransform.Children[1].Angle"
            From="0" To="360" Duration="0:0:1" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers>
</Rectangle>  

在代码中间接以 Freezable 的属性为目标Indirectly Targeting a Property of a Freezable in Code

在代码中,您将创建一个 PropertyPath 对象。In code, you create a PropertyPath object. 当您创建时 PropertyPath ,可以指定 PathPathParametersWhen you create the PropertyPath, you specify a Path and PathParameters.

若要创建 PathParameters ,请创建一个类型为的数组, DependencyProperty 其中包含依赖项属性标识符字段的列表。To create PathParameters, you create an array of type DependencyProperty that contains a list of dependency property identifier fields. 第一个标识符字段用于的属性 FrameworkElementFrameworkContentElement Freezable 用于设置的。The first identifier field is for the property of the FrameworkElement or FrameworkContentElement that the Freezable is used to set. 下一个标识符字段表示目标为的属性 FreezableThe next identifier field represents the property of the Freezable to target. 将其视为一系列将连接到对象的属性 Freezable FrameworkElementThink of it as a chain of properties that connects the Freezable to the FrameworkElement object.

下面是依赖属性链的一个示例,它 Color SolidColorBrush 以用于设置矩形元素的的为目标 FillThe following is an example of a dependency property chain that targets the Color of a SolidColorBrush used to set the Fill of a rectangle element.

DependencyProperty[] propertyChain =
    new DependencyProperty[]
        {Rectangle.FillProperty, SolidColorBrush.ColorProperty};

还需要指定 PathYou also need to specify a Path. Path String ,它指示 Path 如何解释其 PathParametersA Path is a String that tells the Path how to interpret its PathParameters. 它使用以下语法。It uses the following syntax.

( OwnerPropertyArrayIndex ).( FreezablePropertyArrayIndex )( OwnerPropertyArrayIndex ).( FreezablePropertyArrayIndex )

WhereWhere

下面的示例演示 Path PathParameters 前面的示例中定义的。The following example shows the Path that would accompany the PathParameters defined in the preceding example.

DependencyProperty[] propertyChain =
    new DependencyProperty[]
        {Rectangle.FillProperty, SolidColorBrush.ColorProperty};
string thePath = "(0).(1)";

下面的示例合并了前面的示例中的代码,以对 Color SolidColorBrush 用于设置 Fill 矩形元素的的的进行动画处理。The following example combines the code in the previous examples to animate the Color of a SolidColorBrush used to set the Fill of a rectangle element.


// Create a name scope for the page.
NameScope.SetNameScope(this, new NameScope());

Rectangle rectangle01 = new Rectangle();
rectangle01.Name = "Rectangle01";
this.RegisterName(rectangle01.Name, rectangle01);
rectangle01.Width = 100;
rectangle01.Height = 100;
rectangle01.Fill =
    (SolidColorBrush)this.Resources["MySolidColorBrushResource"];

ColorAnimation myColorAnimation = new ColorAnimation();
myColorAnimation.From = Colors.Blue;
myColorAnimation.To = Colors.AliceBlue;
myColorAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTargetName(myColorAnimation, rectangle01.Name);

DependencyProperty[] propertyChain =
    new DependencyProperty[]
        {Rectangle.FillProperty, SolidColorBrush.ColorProperty};
string thePath = "(0).(1)";
PropertyPath myPropertyPath = new PropertyPath(thePath, propertyChain);
Storyboard.SetTargetProperty(myColorAnimation, myPropertyPath);

Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myColorAnimation);
BeginStoryboard myBeginStoryboard = new BeginStoryboard();
myBeginStoryboard.Storyboard = myStoryboard;
EventTrigger myMouseEnterTrigger = new EventTrigger();
myMouseEnterTrigger.RoutedEvent = Rectangle.MouseEnterEvent;
myMouseEnterTrigger.Actions.Add(myBeginStoryboard);
rectangle01.Triggers.Add(myMouseEnterTrigger);

有时,需要以集合或数组中包含的 Freezable 为目标。Sometimes you need to target a freezable contained in a collection or array. 例如,假设某个矩形有一个 TransformGroup 应用于其属性的资源 RenderTransform ,并且您想要对它所包含的其中一个转换进行动画处理。For example, suppose that a rectangle has a TransformGroup resource applied to its RenderTransform property, and you want to animate one of the transforms it contains.

<TransformGroup x:Key="MyTransformGroupResource"
  x:Shared="False">
  <ScaleTransform />
  <RotateTransform />
</TransformGroup>  

若要以 Freezable 集合中包含的为目标,请使用以下路径语法。To target a Freezable contained in a collection, you use the following path syntax.

( OwnerPropertyArrayIndex ).( CollectionChildrenPropertyArrayIndex ) [ CollectionIndex ].( FreezablePropertyArrayIndex )( OwnerPropertyArrayIndex ).( CollectionChildrenPropertyArrayIndex ) [ CollectionIndex ].( FreezablePropertyArrayIndex )

其中, CollectionIndex 是对象在其数组或集合中的索引。Where CollectionIndex is the index of the object in its array or collection.

若要面向的 Angle 属性 RotateTransform (中的第二个转换), TransformGroup 请使用以下 PathPathParametersTo target the Angle property of the RotateTransform, the second transform in the TransformGroup, you would use the following Path and PathParameters.

DependencyProperty[] propertyChain =
    new DependencyProperty[]
        {
            Rectangle.RenderTransformProperty,
            TransformGroup.ChildrenProperty,
            RotateTransform.AngleProperty
        };
string thePath = "(0).(1)[1].(2)";
PropertyPath myPropertyPath = new PropertyPath(thePath, propertyChain);
Storyboard.SetTargetProperty(myDoubleAnimation, myPropertyPath);

下面的示例演示了用于对中包含的的进行动画处理的完整代码 Angle RotateTransform TransformGroupThe following example shows the complete code for animating the Angle of a RotateTransform contained within a TransformGroup.

Rectangle rectangle02 = new Rectangle();
rectangle02.Name = "Rectangle02";
this.RegisterName(rectangle02.Name, rectangle02);
rectangle02.Width = 100;
rectangle02.Height = 100;
rectangle02.Fill = Brushes.Blue;
rectangle02.RenderTransform =
    (TransformGroup)this.Resources["MyTransformGroupResource"];

DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 0;
myDoubleAnimation.To = 360;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTargetName(myDoubleAnimation, rectangle02.Name);

DependencyProperty[] propertyChain =
    new DependencyProperty[]
        {
            Rectangle.RenderTransformProperty,
            TransformGroup.ChildrenProperty,
            RotateTransform.AngleProperty
        };
string thePath = "(0).(1)[1].(2)";
PropertyPath myPropertyPath = new PropertyPath(thePath, propertyChain);
Storyboard.SetTargetProperty(myDoubleAnimation, myPropertyPath);

Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);
BeginStoryboard myBeginStoryboard = new BeginStoryboard();
myBeginStoryboard.Storyboard = myStoryboard;
EventTrigger myMouseEnterTrigger = new EventTrigger();
myMouseEnterTrigger.RoutedEvent = Rectangle.MouseEnterEvent;
myMouseEnterTrigger.Actions.Add(myBeginStoryboard);
rectangle02.Triggers.Add(myMouseEnterTrigger);

间接以 Freezable 为目标并将其作为起点Indirectly Targeting with a Freezable as the Starting Point

前面的部分介绍了如何 Freezable 通过从 FrameworkElement 或开始 FrameworkContentElement 向子属性创建属性链来间接地定位 FreezableThe previous sections described how to indirectly target a Freezable by starting with a FrameworkElement or FrameworkContentElement and creating a property chain to a Freezable sub-property. 你还可以使用 Freezable 作为起点,并间接定位其 Freezable 子属性之一。You can also use a Freezable as a starting point and indirectly target one of its Freezable sub-properties. 当使用作为间接目标的起点时,还可以使用另一种限制 Freezable :起始位置 Freezable 以及 Freezable 它与间接目标的子属性之间的每一个都不能冻结。One additional restriction applies when using a Freezable as a starting point for indirect targeting: the starting Freezable and every Freezable between it and the indirectly targeted sub-property must not be frozen.

在 XAML 中以交互方式控制情节提要Interactively Controlling a Storyboard in XAML

若要在中启动情节提要 可扩展应用程序标记语言 (XAML)Extensible Application Markup Language (XAML) ,请使用 BeginStoryboard 触发器操作。To start a storyboard in 可扩展应用程序标记语言 (XAML)Extensible Application Markup Language (XAML), you use a BeginStoryboard trigger action. BeginStoryboard 将动画分发到它们动画处理的对象和属性,并启动情节提要。BeginStoryboard distributes the animations to the objects and properties they animate, and starts the storyboard. (有关此过程的详细信息,请参阅 动画和计时系统概述。 ) 如果你 BeginStoryboard 通过指定其属性来提供名称 Name ,则会使其成为可控制的情节提要。(For details about this process, see the Animation and Timing System Overview.) If you give the BeginStoryboard a name by specifying its Name property, you make it a controllable storyboard. 然后,可以在情节提要启动后以交互方式对它进行控制。You can then interactively control the storyboard after it's started. 下面列出了可与事件触发器一起使用来控制情节提要的可控制情节提要操作。The following is a list of controllable storyboard actions that you use with event triggers to control a storyboard.

在下面的示例中,使用可控制的情节提要操作来以交互方式控制情节提要。In the following example, controllable storyboard actions are used to interactively control a storyboard.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="Microsoft.SDK.Animation.ControllableStoryboardExample"
  WindowTitle="Fading Rectangle Example">
  <StackPanel Margin="10">

    <Rectangle
      Name="MyRectangle"
      Width="100" 
      Height="100"
      Fill="Blue">
    </Rectangle>

    <Button Name="BeginButton">Begin</Button>
    <Button Name="PauseButton">Pause</Button>
    <Button Name="ResumeButton">Resume</Button>
    <Button Name="SkipToFillButton">Skip To Fill</Button>
    <Button Name="StopButton">Stop</Button>

    <StackPanel.Triggers>
      <EventTrigger RoutedEvent="Button.Click" SourceName="BeginButton">
        <BeginStoryboard Name="MyBeginStoryboard">
          <Storyboard>
            <DoubleAnimation
              Storyboard.TargetName="MyRectangle" 
              Storyboard.TargetProperty="(Rectangle.Opacity)"
              From="1.0" To="0.0" Duration="0:0:5" />
          </Storyboard>
        </BeginStoryboard>
      </EventTrigger>
      <EventTrigger RoutedEvent="Button.Click" SourceName="PauseButton">
        <PauseStoryboard BeginStoryboardName="MyBeginStoryboard" />
      </EventTrigger>
      <EventTrigger RoutedEvent="Button.Click" SourceName="ResumeButton">
        <ResumeStoryboard BeginStoryboardName="MyBeginStoryboard" />
      </EventTrigger>
      <EventTrigger RoutedEvent="Button.Click" SourceName="SkipToFillButton">
        <SkipStoryboardToFill BeginStoryboardName="MyBeginStoryboard" />
      </EventTrigger>
      <EventTrigger RoutedEvent="Button.Click" SourceName="StopButton">
        <StopStoryboard BeginStoryboardName="MyBeginStoryboard" />
      </EventTrigger>
    </StackPanel.Triggers>
  </StackPanel>
</Page>

使用代码以交互方式控制情节提要Interactively Controlling a Storyboard by Using Code

前面的示例已演示了如何使用触发器操作进行动画处理。The previous examples have shown how to animate using trigger actions. 在代码中,你还可以使用类的交互式方法控制情节提要 StoryboardIn code, you may also control a storyboard using interactive methods of the Storyboard class. Storyboard若要在代码中使成为交互,必须使用情节提要的方法的适当重载, Begin 并指定 true 以使其可控制。For a Storyboard to be made interactive in code, you must use the appropriate overload of the storyboard's Begin method and specify true to make it controllable. 有关详细信息,请参阅Begin(FrameworkElement, Boolean)页。See the Begin(FrameworkElement, Boolean) page for more information.

以下列表显示了可用于在启动后操作的方法 StoryboardThe following list shows the methods that can be used to manipulate a Storyboard after it has started:

使用这些方法的优点是不需要创建 TriggerTriggerAction 对象; 只需引用要操作的可控制对象即可 StoryboardThe advantage to using these methods is that you don't need to create Trigger or TriggerAction objects; you just need a reference to the controllable Storyboard you want to manipulate.

备注

对执行的所有交互操作 Clock ,因此,也会在 Storyboard 计时引擎的下一计时周期发生,这将在下一次呈现之前发生。All interactive actions taken on a Clock, and therefore also on a Storyboard will occur on the next tick of the timing engine which will happen shortly before the next render. 例如,如果使用 Seek 方法跳转到动画中的其他点,则属性值不会立即更改,而是在计时引擎的下一计时周期更改。For example, if you use the Seek method to jump to another point in an animation, the property value does not change instantly, rather, the value changes on the next tick of the timing engine.

下面的示例演示如何使用类的交互式方法来应用和控制动画 StoryboardThe following example shows how to apply and control animations using the interactive methods of the Storyboard class.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace SDKSample
{

    public class ControllableStoryboardExample : Page
    {
        private Storyboard myStoryboard;

        public ControllableStoryboardExample()
        {

            // Create a name scope for the page.

            NameScope.SetNameScope(this, new NameScope());

            this.WindowTitle = "Controllable Storyboard Example";
            StackPanel myStackPanel = new StackPanel();
            myStackPanel.Margin = new Thickness(10);

            // Create a rectangle.
            Rectangle myRectangle = new Rectangle();
            myRectangle.Name = "myRectangle";

            // Assign the rectangle a name by
            // registering it with the page, so that
            // it can be targeted by storyboard
            // animations.
            this.RegisterName(myRectangle.Name, myRectangle);
            myRectangle.Width = 100;
            myRectangle.Height = 100;
            myRectangle.Fill = Brushes.Blue;
            myStackPanel.Children.Add(myRectangle);

            //
            // Create an animation and a storyboard to animate the
            // rectangle.
            //
            DoubleAnimation myDoubleAnimation = new DoubleAnimation();
            myDoubleAnimation.From = 1.0;
            myDoubleAnimation.To = 0.0;
            myDoubleAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(5000));
            myDoubleAnimation.AutoReverse = true;

            // Create the storyboard.
            myStoryboard = new Storyboard();
            myStoryboard.Children.Add(myDoubleAnimation);
            Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
            Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Rectangle.OpacityProperty));

            //
            // Create some buttons to control the storyboard
            // and a panel to contain them.
            //
            StackPanel buttonPanel = new StackPanel();
            buttonPanel.Orientation = Orientation.Horizontal;
            Button beginButton = new Button();
            beginButton.Content = "Begin";
            beginButton.Click += new RoutedEventHandler(beginButton_Clicked);
            buttonPanel.Children.Add(beginButton);
            Button pauseButton = new Button();
            pauseButton.Content = "Pause";
            pauseButton.Click += new RoutedEventHandler(pauseButton_Clicked);
            buttonPanel.Children.Add(pauseButton);
            Button resumeButton = new Button();
            resumeButton.Content = "Resume";
            resumeButton.Click += new RoutedEventHandler(resumeButton_Clicked);
            buttonPanel.Children.Add(resumeButton);
            Button skipToFillButton = new Button();
            skipToFillButton.Content = "Skip to Fill";
            skipToFillButton.Click += new RoutedEventHandler(skipToFillButton_Clicked);
            buttonPanel.Children.Add(skipToFillButton);
            Button setSpeedRatioButton = new Button();
            setSpeedRatioButton.Content = "Triple Speed";
            setSpeedRatioButton.Click += new RoutedEventHandler(setSpeedRatioButton_Clicked);
            buttonPanel.Children.Add(setSpeedRatioButton);
            Button stopButton = new Button();
            stopButton.Content = "Stop";
            stopButton.Click += new RoutedEventHandler(stopButton_Clicked);
            buttonPanel.Children.Add(stopButton);
            myStackPanel.Children.Add(buttonPanel);
            this.Content = myStackPanel;
        }

        // Begins the storyboard.
        private void beginButton_Clicked(object sender, RoutedEventArgs args)
        {
            // Specifying "true" as the second Begin parameter
            // makes this storyboard controllable.
            myStoryboard.Begin(this, true);
        }

        // Pauses the storyboard.
        private void pauseButton_Clicked(object sender, RoutedEventArgs args)
        {
            myStoryboard.Pause(this);
        }

        // Resumes the storyboard.
        private void resumeButton_Clicked(object sender, RoutedEventArgs args)
        {
            myStoryboard.Resume(this);
        }

        // Advances the storyboard to its fill period.
        private void skipToFillButton_Clicked(object sender, RoutedEventArgs args)
        {
            myStoryboard.SkipToFill(this);
        }

        // Updates the storyboard's speed.
        private void setSpeedRatioButton_Clicked(object sender, RoutedEventArgs args)
        {
            // Makes the storyboard progress three times as fast as normal.
            myStoryboard.SetSpeedRatio(this, 3);
        }

        // Stops the storyboard.
        private void stopButton_Clicked(object sender, RoutedEventArgs args)
        {
            myStoryboard.Stop(this);
        }
    }
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Shapes
Imports System.Windows.Media
Imports System.Windows.Media.Animation

Namespace SDKSample

    Public Class ControllableStoryboardExample
        Inherits Page
        Private myStoryboard As Storyboard

        Public Sub New()

            ' Create a name scope for the page.

            NameScope.SetNameScope(Me, New NameScope())

            Me.WindowTitle = "Controllable Storyboard Example"
            Dim myStackPanel As New StackPanel()
            myStackPanel.Margin = New Thickness(10)

            ' Create a rectangle.
            Dim myRectangle As New Rectangle()
            myRectangle.Name = "myRectangle"

            ' Assign the rectangle a name by 
            ' registering it with the page, so that
            ' it can be targeted by storyboard
            ' animations.
            Me.RegisterName(myRectangle.Name, myRectangle)
            myRectangle.Width = 100
            myRectangle.Height = 100
            myRectangle.Fill = Brushes.Blue
            myStackPanel.Children.Add(myRectangle)

            '
            ' Create an animation and a storyboard to animate the
            ' rectangle.
            '
            Dim myDoubleAnimation As New DoubleAnimation()
            myDoubleAnimation.From = 1.0
            myDoubleAnimation.To = 0.0
            myDoubleAnimation.Duration = New Duration(TimeSpan.FromMilliseconds(5000))
            myDoubleAnimation.AutoReverse = True

            ' Create the storyboard.
            myStoryboard = New Storyboard()
            myStoryboard.Children.Add(myDoubleAnimation)
            Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name)
            Storyboard.SetTargetProperty(myDoubleAnimation, New PropertyPath(Rectangle.OpacityProperty))

            '
            ' Create some buttons to control the storyboard
            ' and a panel to contain them.
            '
            Dim buttonPanel As New StackPanel()
            buttonPanel.Orientation = Orientation.Horizontal
            Dim beginButton As New Button()
            beginButton.Content = "Begin"
            AddHandler beginButton.Click, AddressOf beginButton_Clicked
            buttonPanel.Children.Add(beginButton)
            Dim pauseButton As New Button()
            pauseButton.Content = "Pause"
            AddHandler pauseButton.Click, AddressOf pauseButton_Clicked
            buttonPanel.Children.Add(pauseButton)
            Dim resumeButton As New Button()
            resumeButton.Content = "Resume"
            AddHandler resumeButton.Click, AddressOf resumeButton_Clicked
            buttonPanel.Children.Add(resumeButton)
            Dim skipToFillButton As New Button()
            skipToFillButton.Content = "Skip to Fill"
            AddHandler skipToFillButton.Click, AddressOf skipToFillButton_Clicked
            buttonPanel.Children.Add(skipToFillButton)
            Dim setSpeedRatioButton As New Button()
            setSpeedRatioButton.Content = "Triple Speed"
            AddHandler setSpeedRatioButton.Click, AddressOf setSpeedRatioButton_Clicked
            buttonPanel.Children.Add(setSpeedRatioButton)
            Dim stopButton As New Button()
            stopButton.Content = "Stop"
            AddHandler stopButton.Click, AddressOf stopButton_Clicked
            buttonPanel.Children.Add(stopButton)
            myStackPanel.Children.Add(buttonPanel)
            Me.Content = myStackPanel


        End Sub

        ' Begins the storyboard.
        Private Sub beginButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
            ' Specifying "true" as the second Begin parameter
            ' makes this storyboard controllable.
            myStoryboard.Begin(Me, True)

        End Sub

        ' Pauses the storyboard.
        Private Sub pauseButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
            myStoryboard.Pause(Me)

        End Sub

        ' Resumes the storyboard.
        Private Sub resumeButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
            myStoryboard.Resume(Me)

        End Sub

        ' Advances the storyboard to its fill period.
        Private Sub skipToFillButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
            myStoryboard.SkipToFill(Me)

        End Sub

        ' Updates the storyboard's speed.
        Private Sub setSpeedRatioButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
            ' Makes the storyboard progress three times as fast as normal.
            myStoryboard.SetSpeedRatio(Me, 3)

        End Sub

        ' Stops the storyboard.
        Private Sub stopButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
            myStoryboard.Stop(Me)

        End Sub

    End Class

End Namespace

在样式中进行动画处理Animate in a Style

可以使用 Storyboard 对象定义中的动画 StyleYou can use Storyboard objects to define animations in a Style. 使用在中的进行动画处理 Storyboard Style 类似于在 Storyboard 其他地方使用,具有以下三个例外:Animating with a Storyboard in a Style is similar to using a Storyboard elsewhere, with the following three exceptions:

  • 不指定 TargetName ; Storyboard 始终以应用到的元素为目标 StyleYou don't specify a TargetName; the Storyboard always targets the element to which the Style is applied. 若要以对象为目标 Freezable ,必须使用间接目标。To target Freezable objects, you must use indirect targeting. 有关间接目标的详细信息,请参阅 间接目标 部分。For more information about indirect targeting, see the Indirect Targeting section.

  • 不能 SourceNameEventTrigger 或指定 TriggerYou can't specify a SourceName for an EventTrigger or a Trigger.

  • 不能使用动态资源引用或数据绑定表达式设置 Storyboard 或动画属性值。You can't use dynamic resource references or data binding expressions to set Storyboard or animation property values. 这是因为内的所有内容都 Style 必须是线程安全的,并且计时系统必须具有 Freeze Storyboard 对象,才能使它们线程安全。That's because everything inside a Style must be thread-safe, and the timing system must FreezeStoryboard objects to make them thread-safe. Storyboard如果无法冻结,则为; 否则它的子时间线包含动态资源引用或数据绑定表达式。A Storyboard cannot be frozen if it or its child timelines contain dynamic resource references or data binding expressions. 有关冻结和其他功能的详细信息 Freezable ,请参阅 " 冻结对象概述"。For more information about freezing and other Freezable features, see the Freezable Objects Overview.

  • 在中 XAMLXAML ,不能为 Storyboard 或动画事件声明事件处理程序。In XAMLXAML, you can't declare event handlers for Storyboard or animation events.

有关演示如何在样式中定义情节提要的示例,请参阅在 样式示例中进行动画处理For an example showing how to define a storyboard in a style, see the Animate in a Style example.

在 ControlTemplate 中进行动画处理Animate in a ControlTemplate

可以使用 Storyboard 对象定义中的动画 ControlTemplateYou can use Storyboard objects to define animations in a ControlTemplate. 使用在中的进行动画处理 Storyboard ControlTemplate 类似于在 Storyboard 其他位置使用,但有以下两个例外:Animating with a Storyboard in a ControlTemplate is similar to using a Storyboard elsewhere, with the following two exceptions:

有关演示如何在中定义情节提要的示例 ControlTemplate ,请参阅 system.windows.controls.controltemplate> 示例中的动画For an example showing how to define a storyboard in a ControlTemplate, see the Animate in a ControlTemplate example.

在属性值更改时进行动画处理Animate When a Property Value Changes

在样式和控件模板中,当属性更改时,可以使用 Trigger 对象来启动情节提要。In styles and control templates, you can use Trigger objects to start a storyboard when a property changes. 有关示例,请参阅在 System.windows.controls.controltemplate> 中 更改属性值并对进行动画处理时触发动画。For examples, see Trigger an Animation When a Property Value Changes and Animate in a ControlTemplate.

属性对象应用的动画的 Trigger 行为方式比 EventTrigger 使用方法启动动画或动画更复杂 StoryboardAnimations applied by property Trigger objects behave in a more complex fashion than EventTrigger animations or animations started using Storyboard methods. 它们使用其他对象定义的动画 "切换" Trigger ,但使用 EventTrigger 和方法触发的动画进行组合。They "handoff" with animations defined by other Trigger objects, but compose with EventTrigger and method-triggered animations.

请参阅See also