Przegląd Scenorysy

W tym temacie pokazano, jak używać obiektów Storyboard do organizowania i stosowania animacji. Opisano w nim sposób interakcyjnego manipulowania obiektami Storyboard i opisano składnię określania wartości docelowej właściwości pośrednich.

Wymagania wstępne

Aby zrozumieć ten temat, należy zapoznać się z różnymi typami animacji i ich podstawowymi funkcjami. Aby uzyskać wprowadzenie do animacji, zobacz Przegląd animacji. Należy również wiedzieć, jak używać dołączonych właściwości. Aby uzyskać więcej informacji na temat dołączonych właściwości, zobacz Przegląd właściwości dołączonych.

Co to jest storyboard

Animacje nie są jedynym przydatnym typem osi czasu. Inne klasy osi czasu ułatwiają organizowanie zestawów osi czasu i stosowanie osi czasu do właściwości. Osie czasu kontenera pochodzą z klasy TimelineGroup i zawierają i ParallelTimelineStoryboard.

A Storyboard to typ osi czasu kontenera, który udostępnia informacje o określaniu wartości docelowej dla osi czasu, które zawiera. Storyboard może zawierać dowolny typ Timeline, w tym inne osie czasu kontenera i animacje. Storyboard Obiekty umożliwiają łączenie osi czasu, które mają wpływ na różne obiekty i właściwości, w jedno drzewo osi czasu, co ułatwia organizowanie i kontrolowanie złożonych zachowań chronometrażu. Załóżmy na przykład, że chcesz mieć przycisk, który robi te trzy rzeczy.

  • Rozwijaj i zmieniaj kolor, gdy użytkownik wybierze przycisk.

  • Zmniejsz rozmiar, a następnie po kliknięciu zmniejsz rozmiar do pierwotnego rozmiaru.

  • Zmniejszanie i zanikanie do 50% przejrzeń po wyłączeniu.

W takim przypadku masz wiele zestawów animacji, które mają zastosowanie do tego samego obiektu, i chcesz odtwarzać w różnych momentach, w zależności od stanu przycisku. Storyboard Obiekty umożliwiają organizowanie animacji i stosowanie ich w grupach do jednego lub większej liczby obiektów.

Gdzie można używać storyboardu

Klasa Storyboard może służyć do animowania właściwości zależności animatywnych klas (aby uzyskać więcej informacji o tym, co sprawia, że klasa jest animowana, zobacz Przegląd animacji). Jednak ponieważ storyboarding jest funkcją na poziomie struktury, obiekt musi należeć do NameScope obiektu typu lub FrameworkElementFrameworkContentElement.

Możesz na przykład użyć funkcji , Storyboard aby wykonać następujące czynności:

Nie można jednak użyć StoryboardSolidColorBrushFrameworkContentElementFrameworkElement obiektu do animowania obiektu , który nie zarejestrł jego nazwy za pomocą lub lub FrameworkElement nie został użyty do ustawienia właściwości lub .FrameworkContentElement

How to Apply Animations with a Storyboard

Aby użyć funkcji do Storyboard organizowania i stosowania animacji, należy dodać animacje jako podrzędne osie czasu Storyboard. Klasa Storyboard udostępnia dołączone Storyboard.TargetNameStoryboard.TargetProperty właściwości i . Te właściwości ustawia się w animacji, aby określić jej obiekt docelowy i właściwość.

Aby zastosować animacje do ich obiektów docelowych, należy rozpocząć Storyboard korzystanie z akcji wyzwalacza lub metody. W języku XAML należy użyć obiektu BeginStoryboard z obiektem EventTrigger, Triggerlub DataTrigger. W kodzie można również użyć Begin metody .

W poniższej tabeli przedstawiono różne miejsca, w których Storyboard jest obsługiwana każda technika rozpoczynania: dla wystąpienia, stylu, szablonu kontrolki i szablonu danych. "Każde wystąpienie" odnosi się do techniki stosowania animacji lub storyboard bezpośrednio do wystąpień obiektu, a nie w stylu, szablonie kontrolki lub szablonie danych.

Storyboard isgun using... Na wystąpienie Styl Szablon kontrolki Szablon danych Przykład
BeginStoryboard i EventTrigger Tak Tak Tak Tak Animowanie właściwości przy użyciu scenorysu
BeginStoryboard i właściwość Trigger Nie Tak Tak Tak Wyzwalanie animacji w przypadku zmiany wartości właściwości
BeginStoryboard i właściwość MultiTrigger Nie Tak Tak Tak Przykład klasy MultiTrigger
BeginStoryboard i a DataTrigger Nie Tak Tak Tak Jak wyzwolić animację po zmianie danych
BeginStoryboard i a MultiDataTrigger Nie Tak Tak Tak Przykład klasy MultiDataTrigger
Metoda Begin Tak Nie Nie Nie Animowanie właściwości przy użyciu scenorysu

W poniższym przykładzie użyto elementu do animowania Width elementu i ColorRectangle elementu używanego SolidColorBrush do malowania elementu Rectangle.Storyboard

<!-- 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;
        }
    }
}

W poniższych sekcjach bardziej szczegółowo opisano TargetNameTargetProperty dołączone właściwości i .

Elementy struktury określania elementów docelowych, elementy zawartości struktury i freezables

W poprzedniej sekcji wspomniano, że aby animacja znalazła element docelowy, musi znać nazwę obiektu docelowego i właściwość do animowania. Określanie właściwości do animowania jest proste: TargetProperty wystarczy ustawić właściwość z nazwą właściwości, aby animować. Należy określić nazwę obiektu, którego właściwość ma być animowana, ustawiając właściwość Storyboard.TargetName animacji.

Przestroga

Chociaż można użyć właściwości Target do powiązania TargetNamebezpośrednio z obiektem jako alternatywy dla , nie jest to możliwe do serializacji. Nie ma gwarancji, że można Target poprawnie odwoływać się do obiektu w języku XAML.

Aby właściwość TargetName działała, obiekt docelowy musi mieć nazwę. Przypisywanie nazwy do obiektu lub FrameworkElement obiektu FrameworkContentElement w języku XAML różni się od przypisywania nazwy do Freezable obiektu.

Elementy struktury to klasy dziedziczące z FrameworkElement klasy . Przykłady elementów struktury to Window, DockPanel, Buttoni Rectangle. Zasadniczo wszystkie okna, panele i kontrolki są elementami. Elementy zawartości struktury to klasy dziedziczące z FrameworkContentElement klasy . Przykłady elementów zawartości struktury to FlowDocument i Paragraph. Jeśli nie masz pewności, czy typ jest elementem struktury, czy elementem zawartości struktury, sprawdź, czy ma właściwość Name. Jeśli tak, prawdopodobnie jest to element struktury lub element zawartości struktury. Aby mieć pewność, sprawdź sekcję Hierarchia dziedziczenia na stronie typu.

Aby włączyć cel elementu struktury lub elementu zawartości struktury w języku XAML, należy ustawić jego właściwość Name . W kodzie należy również użyć metody RegisterName , aby zarejestrować nazwę elementu za pomocą elementu , dla którego utworzono element NameScope.

Poniższy przykład, z poprzedniego przykładu, MyRectangleRectangleprzypisuje nazwę typu , 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);

Po jego nazwie można animować właściwość tego elementu.

<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 typy to klasy dziedziczące z Freezable klasy . Przykłady to FreezableSolidColorBrush, RotateTransformi GradientStop.

Aby włączyć element docelowy elementu przez Freezable animację w języku XAML, należy użyć dyrektywy x:Name, aby przypisać do niego nazwę. W kodzie należy użyć metody RegisterName , aby zarejestrować jej nazwę za pomocą elementu , dla którego utworzono element NameScope.

Poniższy przykład przypisuje nazwę do Freezable obiektu.

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

Obiekt może być następnie celem animacji.

<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 Obiekty używają zakresów nazw do rozpoznawania TargetName właściwości. Aby uzyskać więcej informacji na temat zakresów nazw WPF, zobacz Zakresy nazw WPF XAML. Jeśli właściwość TargetName zostanie pominięta, animacja będzie dotyczyć elementu, na którym jest zdefiniowana, lub, w przypadku stylów, elementu w stylu.

Czasami nazwy nie można przypisać do Freezable obiektu. Jeśli na przykład obiekt jest Freezable zadeklarowany jako zasób lub używany do ustawienia wartości właściwości w stylu, nie może mieć nazwy. Ponieważ nie ma nazwy, nie można jej bezpośrednio określić jako docelowej nazwy, ale można jej użyć pośrednio. W poniższych sekcjach opisano sposób używania pośredniego określania wartości docelowej.

Pośredni cel

Czasami obiekt nie Freezable może być celem animacji, Freezable na przykład gdy element jest zadeklarowany jako zasób lub użyty do ustawienia wartości właściwości w stylu. W takich przypadkach, mimo że nie można go bezpośrednio określić jako docelowego, nadal można animować Freezable obiekt. Zamiast ustawiać właściwość TargetName na Freezablenazwę , należy nadać jej nazwę elementu, do którego Freezable należy "". Na przykład obiekt używany SolidColorBrush do ustawienia elementu Fill prostokąta należy do tego prostokąta. Aby animować pędzl, TargetPropertyFreezableFreezable należy ustawić animacje z łańcuchem właściwości, który rozpoczyna się od właściwości elementu struktury lub elementu zawartości struktury , który został użyty do ustawienia i kończy się właściwością w celu animowania.

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

Pamiętaj, że jeśli obiekt jest Freezable zamrożony, klon zostanie wykonany i ten klon będzie animowany. W takim przypadku właściwość oryginalnego obiektu HasAnimatedPropertiesfalsenadal zwraca wartość , ponieważ oryginalny obiekt nie jest w rzeczywistości animowany. Aby uzyskać więcej informacji na temat klonowania, zobacz Freezable Objects Overview (Omówienie obiektów Freezable).

Należy również zauważyć, że w przypadku używania pośredniego określania wartości docelowej właściwości można kierować obiekty docelowe, które nie istnieją. Można na przykład założyć, BackgroundSolidColorBrush że obiekt określonego przycisku został ustawiony za pomocą przycisku i spróbuje animować jego kolor, LinearGradientBrush gdy w rzeczywistości obiekt został użyty do ustawienia tła przycisku. W takich przypadkach nie jest zgłaszany żaden wyjątek; Animacja nie ma widocznego efektu, ponieważ LinearGradientBrush nie reaguje na zmiany właściwości Color .

W poniższych sekcjach bardziej szczegółowo opisano składnię określania celu właściwości pośrednich.

Pośredni cel właściwości Freezable w XAML

Aby użyć właściwości freezable w języku XAML, użyj następującej składni.

Składnia właściwości
ElementPropertyName.FreezablePropertyName

Lokalizacja

  • ElementPropertyName jest właściwością FrameworkElement obiektu , która Freezable jest używana do ustawienia elementu i

  • FreezablePropertyName jest właściwością obiektu , aby Freezable animować.

Poniższy kod pokazuje, jak animować Color obiekt używany SolidColorBrush do ustawienia elementu Fill prostokąta.

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

Czasami trzeba kierować do obiektu freezable zawartego w kolekcji lub tablicy.

Aby użyć obiektu docelowego freezable zawartego w kolekcji, należy użyć następującej składni ścieżki.

Składnia ścieżki
ElementPropertyName.Children[CollectionIndex].FreezablePropertyName

Gdzie CollectionIndex jest indeksem obiektu w jego tablicy lub kolekcji.

Załóżmy na przykład, że TransformGroupRenderTransform prostokąt ma zasób zastosowany do jego właściwości i chcesz animować jedno z przekształceń, które zawiera.

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

Poniższy kod pokazuje, jak animować właściwość Angle obiektu pokazaną RotateTransform w poprzednim przykładzie.

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

Pośrednio ukierunkowanie właściwości freezable w kodzie

W kodzie tworzysz PropertyPath obiekt . Podczas tworzenia wartości PropertyPathnależy określić wartości i PathPathParameters.

Aby utworzyć PathParametersobiekt , należy utworzyć tablicę typu zawierającą DependencyProperty listę pól identyfikatora właściwości zależności. Pierwsze pole identyfikatora jest dla właściwości FrameworkElementFrameworkContentElement lub , która Freezable jest używana do ustawienia. Następne pole identyfikatora reprezentuje właściwość obiektu docelowego Freezable . Pomyśl o nim jako o łańcuchu właściwości, który łączy obiekt Freezable z obiektem FrameworkElement .

Poniżej przedstawiono przykład łańcucha właściwości ColorSolidColorBrushFill zależności, który jest przeznaczony dla elementu używanego do ustawienia elementu prostokąta.

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

Należy również określić wartość Path. Jest Path to , String który informuje, jak Path interpretować jego .PathParameters Używa następującej składni.

Składnia ścieżki właściwości
(OwnerPropertyArrayIndex).(FreezablePropertyArrayIndex)

Lokalizacja

  • OwnerPropertyArrayIndexDependencyPropertyFrameworkElementFreezable to indeks tablicy, który zawiera identyfikator właściwości obiektu, która jest używana do ustawienia właściwości i

  • FreezablePropertyArrayIndex to indeks DependencyProperty tablicy, który zawiera identyfikator właściwości docelowej.

W poniższym przykładzie pokazano, Path które będą towarzyszyć zdefiniowane PathParameters w poprzednim przykładzie.

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

Poniższy przykład łączy kod z poprzednich przykładów w ColorSolidColorBrushFill celu animowania elementu używanego do ustawienia elementu prostokąta.


// 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);

Czasami trzeba kierować do obiektu freezable zawartego w kolekcji lub tablicy. Załóżmy na przykład, że TransformGroupRenderTransform prostokąt ma zasób zastosowany do jego właściwości i chcesz animować jedno z przekształceń, które zawiera.

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

Aby użyć następującej Freezable składni ścieżki do obiektu docelowego zawartego w kolekcji.

Składnia ścieżki
(OwnerPropertyArrayIndex).(CollectionPropertyArrayIndex)[CollectionIndex].(FreezablePropertyArrayIndex)

Gdzie CollectionIndex jest indeksem obiektu w jego tablicy lub kolekcji.

Aby użyć właściwości Angle obiektu , drugiego przekształcenia TransformGroupw obiekcie , należy użyć następujących wartości i PathPathParameters.RotateTransform

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

W poniższym przykładzie pokazano kompletny kod do animowania Angle tabeli zawartej RotateTransform w .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);

Pośredni cel z freezable jako punktem początkowym

W poprzednich sekcjach opisano, jak FreezableFrameworkElement pośrednio kierować element do obiektu przez rozpoczęcie od lub FrameworkContentElement i utworzenie łańcucha właściwości do właściwości Freezable podrzędnej. Można również użyć jako Freezable punktu początkowego i pośrednio wskazać jedną z jej Freezable właściwości podrzędnych. Jedno dodatkowe ograniczenie ma zastosowanie w przypadku używania jako punktu początkowego pośredniego określania wartości docelowej: FreezableFreezable element początkowy i każdy między nim a Freezable pośrednio docelową właściwością podrzędną nie mogą być zamrożone.

Interakcyjne kontrolowanie storyboardu w XAML

Aby uruchomić storyboard w języku Extensible Application Markup Language (XAML), należy użyć akcji BeginStoryboard wyzwalacza. BeginStoryboard dystrybuuje animacje do obiektów i właściwości, które animują, i uruchamia storyboard. (Aby uzyskać szczegółowe informacje na temat tego procesu, zobacz Przegląd animacji i systemu chronometrażu). Jeśli nadasz BeginStoryboard nazwę, określając jej Name właściwość, możesz ją kontrolować storyboard. Następnie możesz interaktywnie kontrolować storyboard po jego zakończeniu. Poniżej znajduje się lista kontrolowalnych akcji storyboard, których używasz z wyzwalaczami zdarzeń do kontrolowania storyboardu.

W poniższym przykładzie kontrolowanie akcji storyboard jest używane do interaktywnego sterowania 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>

Interakcyjne kontrolowanie storyboardu przy użyciu kodu

W poprzednich przykładach pokazano, jak animować przy użyciu akcji wyzwalacza. W kodzie możesz również kontrolować storyboard przy użyciu interaktywnych metod Storyboard klasy . Aby operator Storyboard był interaktywny w kodzie, należy użyć odpowiedniego przeciążenia metody storyboard Begintrue i określić, aby można było go kontrolować. Zobacz stronę Begin(FrameworkElement, Boolean) , aby uzyskać więcej informacji.

Na poniższej liście przedstawiono metody, których można użyć do manipulowania obiektem Storyboard po jego zakończeniu:

Zaletą korzystania z tych TriggerTriggerAction metod jest to, że nie trzeba tworzyć obiektów ani ich tworzyć. Storyboard Wystarczy odwołanie do kontrolki, którą chcesz manipulować.

Uwaga

Wszystkie akcje interakcyjne wykonane na Clock, Storyboard a tym samym również na , będą występować na następnym taktu aparatu chronometrażu, który nastąpi na krótko przed następnym renderowaniem. Jeśli na przykład Seek użyjemy metody , aby przejść do innego punktu w animacji, wartość właściwości nie zmienia się natychmiast, a raczej wartość zmienia się na następnym taktu aparatu chronometrażu.

W poniższym przykładzie pokazano, jak stosować i kontrolować animacje przy użyciu interaktywnych metod Storyboard klasy.

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

Animuj w stylu

Za pomocą obiektów Storyboard można definiować animacje w .Style Animowanie z w a Storyboard jest Style podobne do używania w innym Storyboard miejscu, z następującymi trzema wyjątkami:

  • Nie określasz elementu ; TargetNameelement Storyboard zawsze jest przeznaczony dla elementu, do którego zastosowano Style element . Do obiektów Freezable docelowych, należy użyć pośredniego określania wartości docelowej. Aby uzyskać więcej informacji na temat pośredniego określania wartości docelowej, zobacz sekcję Cel pośredni .

  • Nie można określić dla SourceName lub EventTriggerTrigger.

  • Nie można używać dynamicznych odwołań do zasobów ani wyrażeń powiązania danych do ustawienia lub Storyboard animacji wartości właściwości. Wynika to z tego, że wszystko wewnątrz obiektu Style musi być bezpieczne wątkowo, a system FreezeStoryboard chronometrażu musi obiektami, aby zapewnić ich bezpieczeństwo wątkowo. A Storyboard nie może być zamrożony, jeśli jego lub jego podrzędne osie czasu zawierają dynamiczne odwołania do zasobów lub wyrażenia powiązania danych. Aby uzyskać więcej informacji na temat zamarzania i innych Freezable funkcji, zobacz Freezable Objects Overview (Omówienie obiektów Freezable).

  • W języku XAML nie można deklarować programów obsługi zdarzeń ani Storyboard zdarzeń animacji.

Aby uzyskać przykład pokazujący sposób definiowania storyboard w stylu, zobacz przykład Animowanie w stylu .

Animuj w ControlTemplate

Za pomocą obiektów Storyboard można definiować animacje w .ControlTemplate Animowanie z w a Storyboard jest ControlTemplate podobne do używania w innym Storyboard miejscu, z następującymi dwoma wyjątkami:

  • Obiekt TargetName może odwoływać się tylko do obiektów podrzędnych obiektu ControlTemplate. Jeśli TargetName nie zostanie określony, animacja będzie dotyczyć elementu, do którego zastosowano ControlTemplate element .

  • Element SourceName dla obiektu EventTrigger lub może Trigger odwoływać się tylko do obiektów podrzędnych obiektu ControlTemplate.

  • Nie można używać dynamicznych odwołań do zasobów ani wyrażeń powiązania danych do ustawienia lub Storyboard animacji wartości właściwości. Wynika to z tego, że wszystko wewnątrz obiektu ControlTemplate musi być bezpieczne wątkowo, a system FreezeStoryboard chronometrażu musi obiektami, aby zapewnić ich bezpieczeństwo wątkowo. A Storyboard nie może być zamrożony, jeśli jego lub jego podrzędne osie czasu zawierają dynamiczne odwołania do zasobów lub wyrażenia powiązania danych. Aby uzyskać więcej informacji na temat zamarzania i innych Freezable funkcji, zobacz Freezable Objects Overview (Omówienie obiektów Freezable).

  • W języku XAML nie można deklarować programów obsługi zdarzeń ani Storyboard zdarzeń animacji.

Aby uzyskać przykład pokazujący sposób definiowania storyboard w tabeli ControlTemplate, zobacz animowanie w przykładzie ControlTemplate .

Animowanie po zmianie wartości właściwości

W szablonach stylów i kontrolek można użyć obiektu Trigger, aby uruchomić storyboard po zmianie właściwości. Przykłady można znaleźć w tematach Trigger an Animation When a Property Value Changes (Wyzwalanie animacji po zmianie wartości właściwości) i Animate in a ControlTemplate (Animowanie w ControlTemplate).

Animacje zastosowane przez obiekty właściwości Trigger zachowują się w bardziej złożony sposób niż EventTrigger animacje lub animacje rozpoczęte przy użyciu Storyboard metod. "Podają" animacje zdefiniowane Trigger przez inne obiekty, ale komponują EventTrigger się z animacjami wyzwalane przez metodę i .

Zobacz też