分鏡腳本概觀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 可用來建立 animatable 類別之相依性屬性的動畫(如需如何 animatable 類別的詳細資訊,請參閱動畫總覽)。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). 不過,因為分鏡腳本是一種架構層級功能,所以物件必須屬於 FrameworkElementFrameworkContentElementNameScopeHowever, 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 來建立未向 FrameworkElementFrameworkContentElement註冊其名稱之 SolidColorBrush 的動畫,或是不會使用它來設定 FrameworkElementFrameworkContentElement的屬性。However, 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 來組織和套用動畫,您可以將動畫新增為 Storyboard的子時間軸。To use a Storyboard to organize and apply animations, you add the animations as child timelines of the Storyboard. Storyboard 類別提供 Storyboard.TargetNameStoryboard.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.

若要將動畫套用至其目標,請使用觸發程式動作或方法開始 StoryboardTo apply animations to their targets, you begin the Storyboard using a trigger action or a method. XAMLXAML中,您可以使用具有 EventTriggerTriggerDataTriggerBeginStoryboard 物件。In 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 樣式Style 控制項範本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
BeginStoryboardDataTriggerBeginStoryboard and a DataTrigger No Yes Yes Yes 操作說明︰在資料變更時觸發動畫How to: Trigger an Animation When Data Changes
Begin 方法Begin method Yes No No No 使用分鏡腳本建立屬性的動畫Animate a Property by Using a Storyboard

下列範例會使用 Storyboard 來建立 Rectangle 元素 Width 的動畫,以及用來繪製該 SolidColorBrushRectangleColorThe 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;
        } 
    }
}

下列章節會更詳細地描述 TargetNameTargetProperty 附加屬性。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. 將屬性指定為動畫的方式很簡單:只需要使用要建立動畫的屬性名稱來設定 Storyboard.TargetPropertySpecifying the property to animate is straight forward: simply set Storyboard.TargetProperty with the name of the property to animate. 您可以藉由設定動畫的 [Storyboard.TargetName] 屬性,指定您想要以動畫顯示其屬性的物件名稱。You specify the name of the object whose property you want to animate by setting the Storyboard.TargetName property on the animation.

若要讓 TargetName 屬性能夠正常執行,目標物件必須具有名稱。For the TargetName property to work, the targeted object must have a name. 將名稱指派給 XAMLXAML 中的 FrameworkElementFrameworkContentElement 與指派 Freezable 物件的名稱不同。Assigning a name to a FrameworkElement or a FrameworkContentElement in XAMLXAML is different than assigning a name to a Freezable object.

架構元素是繼承自 FrameworkElement 類別的類別。Framework 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. 架構內容元素是繼承自 FrameworkContentElement 類別的類別。Framework 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. 如果有,它可能是架構元素或架構內容元素。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中啟用 framework 元素或架構內容專案的目標,您可以設定其 Name 屬性。To enable the targeting of a framework element or a framework content element in XAMLXAML, you set its Name property. 在程式碼中,您也需要使用 RegisterName 方法,向您已建立 NameScope的專案註冊元素的名稱。In 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 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 類型是繼承自 Freezable 類別的類別。Freezable types are those classes that inherit from the Freezable class. Freezable 的範例包括 SolidColorBrushRotateTransformGradientStopExamples of Freezable include SolidColorBrush, RotateTransform, and GradientStop.

若要在 XAMLXAML中啟用動畫的目標 Freezable,您可以使用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 方法,向您已建立 NameScope的元素註冊其名稱。In 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. 在這些情況下,即使您無法直接將其設為目標,仍然可以建立 Freezable 物件的動畫。In these cases, even though you can't target it directly, you can still animate the Freezable object. 您不需要使用 Freezable的名稱來設定 TargetName 屬性,而是指定 Freezable 「所屬」的元素名稱。Instead of setting the TargetName property with the name of the Freezable, you give it the name of the element to which the Freezable "belongs." 例如,用來設定矩形元素 FillSolidColorBrush 是屬於該矩形。For example, a SolidColorBrush used to set the Fill of a rectangle element belongs to that rectangle. 若要建立筆刷的動畫,您會將動畫的 TargetProperty 設定為從 framework 專案或架構內容專案的屬性開始的屬性鏈,而此 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 不會對 Color 屬性的變更做出反應,所以動畫無法具有可見效果。In 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

其中Where

下列程式碼示範如何以動畫顯示用來設定矩形元素 FillSolidColorBrush ColorThe 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>

下列程式碼示範如何以動畫顯示上一個範例中所示之 RotateTransformAngle 屬性。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. 第一個識別碼欄位適用于 FrameworkElement 的屬性,或 Freezable 用來設定的 FrameworkContentElementThe first identifier field is for the property of the FrameworkElement or FrameworkContentElement that the Freezable is used to set. 下一個 [識別碼] 欄位代表要設為目標之 Freezable 的屬性。The next identifier field represents the property of the Freezable to target. 將它想成是將 Freezable 連接到 FrameworkElement 物件的一環屬性。Think of it as a chain of properties that connects the Freezable to the FrameworkElement object.

以下是相依性屬性鏈的範例,其以用來設定矩形元素 FillSolidColorBrush Color 為目標。The 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 是告訴 Path 如何解讀其 PathParametersStringA Path is a String that tells the Path how to interpret its PathParameters. 它會使用下列語法。It uses the following syntax.

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

其中Where

下列範例會顯示先前範例中所定義之 PathParameters 隨附的 PathThe 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)";

下列範例會結合上述範例中的程式碼,以動畫顯示用來設定矩形元素 FillSolidColorBrushColorThe 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.

若要以 RotateTransformAngle 屬性為目標,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);

下列範例顯示的完整程式碼,可用於建立包含在 TransformGroup內之 RotateTransform Angle 的動畫。The 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

前面幾節說明了如何藉由 FrameworkElementFrameworkContentElement 開始,以及建立 Freezable 子屬性的屬性鏈,間接地以 Freezable 為目標。The 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

若要在 Extensible Application Markup Language (XAML)Extensible Application Markup Language (XAML)中啟動分鏡腳本,您可以使用 BeginStoryboard 觸發程式動作。To start a storyboard in Extensible Application Markup Language (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. (如需此程式的詳細資訊,請參閱動畫和計時系統總覽)。如果您藉由指定 Name 屬性來提供 BeginStoryboard 名稱,則會將它設為可控制的分鏡腳本。(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. 在程式碼中,您也可以使用 Storyboard 類別的互動方法來控制分鏡腳本。In 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.

下列清單顯示在啟動之後,可以用來操作 Storyboard 的方法:The 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.

下列範例顯示如何使用 Storyboard 類別的互動方法來套用和控制動畫。The 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 物件來定義 Style中的動畫。You can use Storyboard objects to define animations in a Style. Style 中使用 Storyboard 建立動畫類似于在別處使用 Storyboard,但有下列三個例外:Animating with a Storyboard in a Style is similar to using a Storyboard elsewhere, with the following three exceptions:

  • 您未指定 TargetName;Storyboard 一律以套用 Style 的專案為目標。You 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.

  • 您不能指定 EventTriggerTriggerSourceNameYou 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 內的所有專案都必須是安全線程,而且計時系統必須 FreezeStoryboard 物件,才能使其具備執行緒安全。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 物件來定義 ControlTemplate中的動畫。You can use Storyboard objects to define animations in a ControlTemplate. ControlTemplate 中使用 Storyboard 建立動畫,類似于使用其他地方的 Storyboard,但有下列兩個例外狀況:Animating with a Storyboard in a ControlTemplate is similar to using a Storyboard elsewhere, with the following two exceptions:

如需示範如何在 ControlTemplate中定義分鏡腳本的範例,請參閱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. 如需範例,請參閱當屬性值變更時觸發動畫,並在 ControlTemplate 中建立動畫For examples, see Trigger an Animation When a Property Value Changes and Animate in a ControlTemplate.

屬性 Trigger 物件所套用的動畫,其行為方式會比 EventTrigger 動畫或使用 Storyboard 方法開始的動畫更複雜。Animations 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