分鏡腳本概觀

本主題說明如何使用 Storyboard 物件來組織和套用動畫。 它描述如何以互動方式操作 Storyboard 物件,並描述間接屬性目標語法。

先決條件

若要了解本主題,您應該熟悉不同的動畫類型及其基本功能。 如需動畫的簡介,請參閱動畫概觀。 您也應該了解如何使用附加屬性。 如需附加屬性的詳細資訊,請參閱附加屬性概觀

什麼是分鏡腳本

動畫不是唯一有用的時間軸型別。 還有其他時間軸類別可以協助您組織時間軸集合,以及將時間軸套用至屬性。 容器時程表衍生自 TimelineGroup 類別,並包含 ParallelTimelineStoryboard

Storyboard是容器時間軸的類型,可提供其包含之時間軸的目標資訊。 分鏡腳本可以包含任何類型的 Timeline ,包括其他容器時程表和動畫。 Storyboard 物件可讓您將影響各種物件和屬性的時程表結合成單一時間軸樹狀結構,讓您輕鬆組織及控制複雜的計時行為。 例如,假設您想讓按鈕執行下列三個動作。

  • 在使用者選取按鈕時放大及變更色彩。

  • 按一下按鈕時縮小再放大回原本大小。

  • 在停用時縮小並淡化到 50% 的不透明度。

在此案例中,您有多組套用至同一個物件的動畫,並且想要視按鈕的狀態在不同時間播放。 Storyboard 物件可讓您組織動畫,並將其套用在群組中至一或多個物件。

您可以在何處使用分鏡腳本

Storyboard可用來建立可動畫類別之相依性屬性的動畫效果 (,以取得可讓類別產生動畫效果的詳細資訊,請參閱動畫概觀) 。 不過,因為分鏡腳本是架構層級的功能,所以物件必須屬於 NameScopeFrameworkContentElementFrameworkElement

例如,您可以使用 Storyboard 來執行下列動作:

不過,您無法使用 Storyboard 以動畫顯示 SolidColorBrush 未向 或 FrameworkContentElement 註冊其名稱 FrameworkElement 的 ,或 未用來設定 或 FrameworkContentElement 的屬性 FrameworkElement

如何以分鏡腳本套用動畫

若要使用 Storyboard 來組織和套用動畫,您可以將動畫新增為 的 Storyboard 子時程表。 類別 Storyboard 提供 Storyboard.TargetNameStoryboard.TargetProperty 附加屬性。 您可以設定動畫的這些屬性以指定其目標物件和屬性。

若要將動畫套用至其目標,請使用觸發程式動作或方法開始 Storyboard 。 在 XAML 中,您會使用 BeginStoryboard 物件搭配 EventTriggerTriggerDataTrigger 。 在程式碼中,您也可以使用 Begin 方法。

下表顯示支援每個 Storyboard 開始技術的不同位置:每個實例、樣式、控制項範本和資料範本。 「每個執行個體」指的是將動畫或分鏡腳本直接套用至物件之執行個體,而非樣式、控制項範本或資料範本的技術。

開始分鏡腳本的方法… 每個執行個體 樣式 控制項範本 資料範本 範例
BeginStoryboardEventTrigger Yes Yes Yes Yes 使用分鏡腳本建立屬性的動畫
BeginStoryboard 和 屬性 Trigger Yes 在屬性值變更時觸發動畫
BeginStoryboard 和 屬性 MultiTrigger Yes Yes MultiTrigger 類別範例
BeginStoryboardDataTrigger Yes Yes 操作說明︰在資料變更時觸發動畫
BeginStoryboardMultiDataTrigger Yes Yes MultiDataTrigger 類別範例
Begin 方法 使用分鏡腳本建立屬性的動畫

下列範例會使用 Storyboard ,以動畫顯示 RectangleWidth 專案的 ,以及 ColorSolidColorBrush 用來繪製該 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 附加屬性。

以架構元素、架構內容元素和 Freezable 為目標

上一節提到,動畫若要尋找其目標,它必須知道目標的名稱和要建立動畫的屬性。 指定要產生動畫的屬性是直接的:只要 TargetProperty 使用屬性的名稱設定即可產生動畫效果。 您可以藉由在動畫上設定 Storyboard.TargetName 屬性來指定物件的名稱,其屬性要產生動畫效果。

警告

雖然您可以使用 Target 屬性直接系結至 物件做為 替代 TargetName 專案,但無法序列化。 不保證 Target 物件可以在 XAML 中正確參考。

TargetName若要讓 屬性能夠運作,目標物件必須具有名稱。 將名稱指派給 FrameworkElementFrameworkContentElement XAML 中的 ,與將名稱指派給 Freezable 物件不同。

Framework 元素是繼承自 類別的 FrameworkElement 類別。 架構元素的範例包括 WindowDockPanelButtonRectangle 。 基本上所有的視窗、面板和控制項都是元素。 架構內容元素是繼承自 類別的 FrameworkContentElement 類別。 架構內容專案的範例包括 FlowDocumentParagraph 。 如果您不確定某個型別是架構元素或架構內容元素,請檢查它是否具有 Name 屬性。 如果有,它可能是架構元素或架構內容元素。 為了安全起見,請檢查其型別頁面的<繼承階層>一節。

若要在 XAML 中啟用架構專案或架構內容專案的目標,您可以設定其 Name 屬性。 在程式碼中 RegisterName ,您也需要使用 方法來向您已建立 NameScope 的 元素註冊專案名稱。

下列範例取自上述範例,會指派名稱 MyRectangle a Rectangle ,類型為 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);

在元素具有名稱後,您就可以為該元素的屬性建立動畫。

<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 範例包括 SolidColorBrushRotateTransformGradientStop

若要啟用 XAML 中動畫的目標 Freezable ,您可以使用 x:Name 指示詞 將名稱指派給它。 在程式碼中 RegisterName ,您可以使用 方法來向您已建立 NameScope 的 元素註冊其名稱。

下列範例會將名稱指派給 Freezable 物件。

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

然後物件可以作為動畫的目標。

<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 屬性。 如需 WPF 名稱範圍的詳細資訊,請參閱 WPF XAML 名稱範圍TargetName如果省略 屬性,動畫會以其定義所在的專案為目標,或者,如果是樣式,則為樣式專案。

有時無法將名稱指派給 Freezable 物件。 例如,如果 Freezable 宣告為資源,或用來在樣式中設定屬性值,則無法指定名稱。 因為它沒有名稱,就無法直接做為目標,但可間接做為目標。 以下各節會說明如何使用間接目標。

間接目標

Freezable有時候動畫無法直接鎖定 ,例如 Freezable 當 宣告為資源或用來設定樣式中的屬性值時。 在這些情況下,即使您無法直接將它設為目標,您仍然可以讓 Freezable 物件產生動畫效果。 您不要使用 的名稱 Freezable 來設定 TargetName 屬性,而是將 「所屬」的專案名稱 Freezable 提供給它。例如, SolidColorBrush 用來設定 Fill 矩形專案的 屬於該矩形。 若要建立筆刷的動畫效果,您可以使用屬性鏈結來設定動畫 TargetProperty ,該屬性會從 用來設定的架構元素或架構內容元素 Freezable 的 屬性開始,並以 Freezable 屬性為動畫效果結束。

<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 已凍結,則會製作複製品,而該複製將會以動畫顯示。 發生這種情況時,原始物件的 HasAnimatedProperties 屬性會繼續傳回 false ,因為原始物件實際上不會產生動畫效果。 如需複製的詳細資訊,請參閱 Freezable 物件概觀

另請注意,當使用間接屬性目標時,可能會以不存在的物件作為目標。 例如,您可能會假設 Background 特定按鈕的 設定為 , SolidColorBrush 並嘗試以動畫顯示其 Color,而事實上 LinearGradientBrush ,用來設定按鈕的背景。 在這些情況下,不會擲回任何例外狀況;動畫無法顯示效果,因為 LinearGradientBrush 不會回應屬性的 Color 變更。

以下各節會詳細說明間接屬性目標語法。

在 XAML 中以 Freezable 屬性為間接目標

若要以 XAML 中 freezable 的屬性為目標,請使用下列語法。

屬性語法
ElementPropertyName.FreezablePropertyName

Where

下列程式碼示範如何以動畫顯示 ColorSolidColorBrush 用來設定 Fill 矩形專案的 。

<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 為目標。

若要以集合中包含的 Freezable 為目標,請使用下列路徑語法。

路徑語法
ElementPropertyName.Children[CollectionIndex].FreezablePropertyName

其中 CollectionIndex 是其陣列或集合中物件的索引。

例如,假設矩形已 TransformGroup 將資源套用至其 RenderTransform 屬性,而您想要讓其中一個包含的轉換產生動畫效果。

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

下列程式碼示範如何以動畫顯示 Angle 上一個範例所示 的 RotateTransform 屬性。

<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 的屬性為間接目標

在程式碼中,您會建立 PropertyPath 物件。 當您建立 PropertyPath 時,您會指定 PathPathParameters

若要建立 PathParameters ,您可以建立類型的 DependencyProperty 陣列,其中包含相依性屬性識別碼欄位的清單。 第一個識別碼欄位是 用於 的 屬性 FrameworkElement ,或 FrameworkContentElementFreezable 用來設定的 。 下一個識別碼欄位代表要目標的 屬性 Freezable 。 請將它視為將 連接到 FrameworkElement 物件的屬性 Freezable 鏈結。

以下是相依性屬性鏈結的範例,其目標為 ColorSolidColorBrush 用來設定 Fill 矩形專案的 。

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

您也需要指定 PathPath是 , String 告知 Path 如何解譯其 PathParameters 。 它會使用下列語法。

屬性路徑語法
(OwnerPropertyArrayIndex).(FreezablePropertyArrayIndex)

Where

下列範例顯示 PathPathParameters 隨附于上述範例中定義的 。

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

下列範例會結合上述範例中的程式碼,以動畫顯示 ColorSolidColorBrush 用來設定 Fill 矩形專案的 。


// 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 為目標。 例如,假設矩形已 TransformGroup 將資源套用至其 RenderTransform 屬性,而您想要讓其中一個包含的轉換產生動畫效果。

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

若要以集合中包含的 為目標 Freezable ,請使用下列路徑語法。

路徑語法
(OwnerPropertyArrayIndex).(CollectionChildrenPropertyArrayIndex)[CollectionIndex].(FreezablePropertyArrayIndex)

其中 CollectionIndex 是其陣列或集合中物件的索引。

若要以 AngleRotateTransform 屬性為目標,您會使用下列 PathPathParameters 中的第二個 TransformGroup 轉換。

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 內所含 的 RotateTransformTransformGroup

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 作為起點的間接目標

上一節說明如何從 或 FrameworkContentElement 開始 FrameworkElement 間接鎖定 Freezable ,以及建立子屬性的屬性鏈 Freezable 結。 您也可以使用 Freezable 作為起點,並間接以其中 Freezable 一個子屬性為目標。 使用 做為間接目標的起點時,會套用 Freezable 一項額外的限制:開始 Freezable 和其與間接目標子屬性之間的每 Freezable 一個都不得凍結。

在 XAML 中以互動方式控制分鏡腳本

若要在 Extensible Application Markup Language (XAML) 中啟動分鏡腳本,請使用 BeginStoryboard 觸發程式動作。 BeginStoryboard 會將動畫散發至動畫的物件和屬性,然後啟動分鏡腳本。 (如需此程式的詳細資訊,請參閱動畫和計時系統概觀。) 如果您藉由指定其 Name 屬性來指定 BeginStoryboard 名稱,請將它設為可控制的分鏡腳本。 接著在分鏡腳本啟動後,您就可能以互動方式控制它。 以下是可控制之分鏡腳本動作的清單,您可以將這些動作與事件觸發程序搭配使用以控制分鏡腳本。

在下列範例中,會使用可控制的分鏡腳本動作以互動方式控制分鏡腳本。

<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>

使用程式碼以互動方式控制分鏡腳本

前述範例顯示如何使用觸發動作顯示動畫。 在程式碼中,您也可以使用 類別的 Storyboard 互動式方法來控制分鏡腳本。 Storyboard若要在程式碼中建立互動式的 ,您必須使用腳本方法的適當多載 Begin ,並指定 true 以使其可控制。 如需詳細資訊,請參閱Begin(FrameworkElement, Boolean)頁面。

下列清單顯示可用來在啟動之後操作 Storyboard 的方法:

使用這些方法的優點是,您不需要建立 TriggerTriggerAction 物件;您只需要參考您想要操作的可 Storyboard 控制。

注意

在 上 Clock 採取的所有互動式動作,因此也會 Storyboard 在計時引擎的下一個刻度上發生,該引擎會在下一次轉譯之前不久發生。 例如,如果您使用 Seek 方法跳至動畫中的另一個點,屬性值不會立即變更,而是在計時引擎的下一個刻度變更值。

下列範例示範如何使用 類別的 Storyboard 互動式方法來套用和控制動畫。

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

在樣式中建立動畫

您可以使用 Storyboard 物件在 中 Style 定義動畫。 Storyboard在 中使用 動畫 Style 的方式類似于使用其他地方,但有下列三個 Storyboard 例外狀況:

  • 您未指定 TargetName ,一 Storyboard 律會將 Style 套用 的專案設為目標。 若要以物件為目標 Freezable ,您必須使用間接目標。 如需間接目標的詳細資訊,請參閱 間接目標 一節。

  • 您無法為 EventTriggerTrigger 指定 SourceName

  • 您無法使用動態資源參考或資料系結運算式來設定 Storyboard 或動畫屬性值。 這是因為 內 Style 的所有專案都必須是安全線程,而計時系統必須 FreezeStoryboard 有 物件,才能讓它們成為安全線程。 Storyboard如果它或其子時間軸包含動態資源參考或資料系結運算式,則無法凍結 。 如需凍結和其他 Freezable 功能的詳細資訊,請參閱 Freezable 物件概觀

  • 在 XAML 中,您無法宣告 Storyboard 或 動畫事件的事件處理常式。

如需示範如何在樣式中定義分鏡腳本的範例,請參閱 Style 範例中的動畫

在 ControlTemplate 中建立動畫

您可以使用 Storyboard 物件在 中 ControlTemplate 定義動畫。 Storyboard在 中使用 動畫 ControlTemplate 的方式類似于使用其他地方,但有下列兩個 Storyboard 例外狀況:

如需示範如何在 中 ControlTemplate 定義分鏡腳本的範例,請參閱 ControlTemplate 範例中的 Animate

在屬性值變更時建立動畫

在樣式和控制項範本中,您可以使用 Trigger 物件在屬性變更時啟動分鏡腳本。 如需範例,請參閱在ControlTemplate 中觸發屬性值變更和動畫時觸發動畫。

屬性 Trigger 物件所套用的動畫行為比使用 Storyboard 方法開始的動畫或動畫更為複雜 EventTrigger 。 它們會以其他 Trigger 物件定義的動畫「遞交」,但會使用 EventTrigger 和 方法觸發的動畫來撰寫。

另請參閱