Przegląd Scenorysy

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

Wymagania wstępne

Aby zrozumieć ten temat, należy zapoznać się z różnymi typami animacji i ich podstawowymi funkcjami. Aby zapoznać się z wprowadzeniem do animacji, zobacz Omówienie 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 Omówienie dołączonych właściwości.

Co to jest scenorys

Animacje nie są jedynym przydatnym typem osi czasu. Dostępne są inne klasy osi czasu, które ułatwiają organizowanie zestawów osi czasu oraz stosowanie osi czasu do właściwości. Osie czasu kontenera pochodzą z TimelineGroup klasy oraz dołączania ParallelTimeline i Storyboard.

Element Storyboard to typ osi czasu kontenera, który zawiera informacje o określaniu wartości docelowej dla zawartych w nim osi czasu. Scenorys 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 jednym drzewie osi czasu, co ułatwia organizowanie i kontrolowanie złożonych zachowań chronometrażu. Załóżmy na przykład, że potrzebujesz przycisku, który wykonuje te trzy czynności.

  • Zwiększ i zmień kolor po wybraniu przycisku przez użytkownika.

  • Zmniejsz rozmiar, a następnie wróć do oryginalnego rozmiaru po kliknięciu.

  • Zmniejsz i zanikaj do 50 procent nieprzezroczystości, gdy staje się wyłączony.

W takim przypadku masz wiele zestawów animacji, które mają zastosowanie do tego samego obiektu, i chcesz grać w różnym czasie, w zależności od stanu przycisku. Storyboard obiekty umożliwiają organizowanie animacji i stosowanie ich w grupach do co najmniej jednego obiektu.

Gdzie można użyć scenorysu

Element Storyboard może służyć do animowania właściwości zależności klas animatowalnych (aby uzyskać więcej informacji na temat tego, co sprawia, że klasa jest animatowalne, zobacz Omówienie animacji). Jednak ze względu na to, że scenorys jest funkcją na poziomie platformy, obiekt musi należeć do NameScope obiektu FrameworkElement lub FrameworkContentElement.

Na przykład można użyć elementu , Storyboard aby wykonać następujące czynności:

Nie można jednak użyć obiektu , Storyboard aby animować elementu SolidColorBrush , który nie zarejestrował jego nazwy za pomocą FrameworkElement elementu lub FrameworkContentElementlub , lub nie został użyty do ustawienia właściwości FrameworkElement lub FrameworkContentElement.

Jak stosować animacje za pomocą scenorysu

Aby użyć elementu Storyboard do organizowania i stosowania animacji, należy dodać animacje jako podrzędne osie Storyboardczasu . Klasa Storyboard udostępnia Storyboard.TargetName właściwości i Storyboard.TargetProperty dołączone. Te właściwości można ustawić na 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 używasz BeginStoryboard obiektu 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 jest obsługiwana każda Storyboard technika rozpoczęcia: na wystąpienie, styl, szablon kontrolki i szablon danych. Wyrażenie "Per-Instance" odnosi się do techniki stosowania animacji lub scenorysu bezpośrednio do wystąpień obiektu, a nie w stylu, szablonie kontrolki lub szablonie danych.

Scenorys zaczyna używać... 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 Instrukcje: wyzwalanie animacji po zmianie danych
BeginStoryboard i a MultiDataTrigger Nie. Tak Tak Tak Przykład klasy MultiDataTrigger
Begin Metoda Tak Nie Nie. Nie. Animowanie właściwości przy użyciu scenorysu

W poniższym przykładzie użyto elementu do Storyboard animowania RectangleWidth elementu i Color elementu użytego SolidColorBrush do malowania elementu 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;
        }
    }
}

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

Określanie wartości docelowych elementów struktury, elementów zawartości struktury i zamrażania

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

Uwaga

Chociaż można użyć Target właściwości do powiązania bezpośrednio z obiektem jako alternatywy dla TargetNameelementu , nie można go serializować. Nie ma gwarancji, że Target obiekt może być poprawnie przywołyny w języku XAML.

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

Elementy struktury to te klasy, które dziedziczą po FrameworkElement klasie. Przykłady elementów struktury to Window, , DockPanelButtoni Rectangle. Zasadniczo wszystkie okna, panele i kontrolki są elementami. Elementy zawartości struktury to te klasy dziedziczone z FrameworkContentElement klasy. Przykłady elementów zawartości platformy 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 upewnić się, sprawdź sekcję Hierarchia dziedziczenia na swojej stronie typu.

Aby włączyć określanie wartości docelowej elementu struktury lub elementu zawartości struktury w języku XAML, należy ustawić jego Name właściwość. W kodzie należy również użyć RegisterName metody , aby zarejestrować nazwę elementu przy użyciu elementu, dla którego utworzono NameScopeelement .

Poniższy przykład, pobrany z poprzedniego przykładu, przypisuje nazwę MyRectangleRectangle, typ 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 utworzeniu nazwy 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 te klasy dziedziczone z Freezable klasy. Przykłady obejmują FreezableSolidColorBrush, RotateTransformi GradientStop.

Aby włączyć określanie wartości docelowej Freezable elementu przez animację w języku XAML, należy użyć dyrektywy x:Name, aby przypisać jej nazwę. W kodzie użyjesz metody , aby zarejestrować jej nazwę za pomocą RegisterName elementu, dla którego utworzono NameScopeelement .

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 kierowany przez animację.

<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 WPF XAML Namescopes. TargetName Jeśli właściwość zostanie pominięta, animacja jest przeznaczona dla elementu, na którym jest zdefiniowany, lub, w przypadku stylów, stylizowany element.

Czasami nie można przypisać nazwy do Freezable obiektu. Jeśli na przykład element Freezable jest zadeklarowany jako zasób lub używany do ustawiania wartości właściwości w stylu, nie można nadać mu nazwy. Ponieważ nie ma nazwy, nie można jej stosować bezpośrednio — ale można ją zastosować pośrednio. W poniższych sekcjach opisano sposób używania określania wartości docelowych pośrednich.

Określanie wartości docelowej pośredniej

Freezable Czasami nie można zastosować bezpośrednio animacji, na przykład wtedy, gdy Freezable element jest zadeklarowany jako zasób lub służy do ustawiania wartości właściwości w stylu. W takich przypadkach, mimo że nie można go bezpośrednio kierować, nadal można animować Freezable obiektu. Zamiast ustawiać TargetName właściwość o nazwie Freezable, należy nadać jej nazwę elementu, do którego Freezable należy . Na przykład element SolidColorBrush używany do ustawiania Fill elementu prostokąta należy do tego prostokąta. Aby animować szczotkę, należy ustawić animację TargetProperty z łańcuchem właściwości rozpoczynających się od właściwości elementu struktury lub elementu Freezable zawartości struktury, który został użyty do ustawienia i kończy się właściwością Freezable do 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);

Należy pamiętać, że jeśli Freezable element jest zamrożony, zostanie wykonany klon, a klon zostanie animowany. W takim przypadku właściwość oryginalnego obiektu HasAnimatedProperties nadal zwraca falsewartość , ponieważ oryginalny obiekt nie jest rzeczywiście animowany. Aby uzyskać więcej informacji na temat klonowania, zobacz Omówienie obiektów zamrażalnych.

Należy również pamiętać, że w przypadku używania określania wartości docelowej właściwości pośredniej można użyć obiektów docelowych, które nie istnieją. Można na przykład założyć, że Background element określonego przycisku został ustawiony za pomocą elementu SolidColorBrush i spróbuj animować jego kolor, gdy w rzeczywistości LinearGradientBrush element został użyty do ustawienia tła przycisku. W takich przypadkach nie jest zgłaszany żaden wyjątek; animacja nie może mieć widocznego efektu, ponieważ LinearGradientBrush nie reaguje na zmiany Color właściwości.

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

Pośrednio określania wartości docelowej właściwości zamrażalnej w języku XAML

Aby zastosować właściwość mroźną w języku XAML, użyj następującej składni.

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

Gdzie

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

  • FreezablePropertyName jest właściwością Freezable do animowania.

Poniższy kod pokazuje, jak animować ColorSolidColorBrush element używany do ustawiania Fill elementu 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 konieczne jest określenie wartości docelowej, którą można zamrozić w kolekcji lub tablicy.

Aby zastosować obiekt docelowy zamrażalny zawarty w kolekcji, należy użyć następującej składni ścieżki.

Składnia XPath
ElementPropertyName.Children[CollectionIndex].FreezablePropertyName

Gdzie CollectionIndex jest indeksem obiektu w tablicy lub kolekcji.

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

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

Poniższy kod pokazuje, jak animować Angle właściwość 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 zamrażalnej w kodzie

W kodzie utworzysz PropertyPath obiekt. Podczas tworzenia elementu PropertyPathnależy określić element Path i PathParameters.

Aby utworzyć PathParametersobiekt , należy utworzyć tablicę typu DependencyProperty zawierającą listę pól identyfikatora właściwości zależności. Pierwszym polem identyfikatora jest właściwość FrameworkElement lub FrameworkContentElement , która Freezable jest używana do ustawienia. Następne pole identyfikatora reprezentuje właściwość Freezable elementu docelowego do. Pomyśl o nim jako łańcuch właściwości łączących Freezable obiekt z obiektem FrameworkElement .

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

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

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

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

Gdzie

  • OwnerPropertyArrayIndex jest indeksem DependencyProperty tablicy zawierającej identyfikator FrameworkElement właściwości obiektu, która Freezable jest używana do ustawienia, i

  • FreezablePropertyArrayIndex jest indeksem DependencyProperty tablicy zawierającej identyfikator właściwości docelowej.

W poniższym przykładzie pokazano element Path , który będzie towarzyszyć PathParameters zdefiniowanemu w poprzednim przykładzie.

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

Poniższy przykład łączy kod w poprzednich przykładach, aby animować ColorSolidColorBrush element używany do ustawiania Fill 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 konieczne jest określenie wartości docelowej, którą można zamrozić w kolekcji lub tablicy. Załóżmy na przykład, że prostokąt ma TransformGroup zasób zastosowany do jego RenderTransform właściwości i chcesz animować jeden z przekształceń, które zawiera.

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

Aby zastosować element docelowy Freezable zawarty w kolekcji, należy użyć następującej składni ścieżki.

Składnia XPath
(OwnerPropertyArrayIndex CollectionChildrenPropertyArrayIndex CollectionIndex FreezablePropertyArrayIndex[)].().()

Gdzie CollectionIndex jest indeksem obiektu w tablicy lub kolekcji.

Aby zastosować Angle właściwość RotateTransform, druga transformacja w TransformGroupobiekcie , należy użyć następujących Path elementów i 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);

W poniższym przykładzie pokazano kompletny kod umożliwiający animowanie Angle elementu zawartego RotateTransform w obiekcie 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średnie określanie wartości docelowej z zamrażalnym punktem początkowym

W poprzednich sekcjach opisano sposób pośredniego określania wartości docelowej Freezable przez rozpoczęcie od elementu FrameworkElement lub FrameworkContentElement i utworzenie łańcucha właściwości do Freezable podwłaszej właściwości. Można również użyć jako Freezable punktu początkowego i pośrednio wskazać jedną z jego Freezable właściwości podrzędnych. Jedno dodatkowe ograniczenie ma zastosowanie w przypadku użycia Freezable jako punktu początkowego dla kierowania pośredniego: początkowe Freezable i każde Freezable między nim a pośrednio docelową właściwością podrzędną nie może być zamrożone.

Interaktywne kontrolowanie scenorysu w języku XAML

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

W poniższym przykładzie akcje scenorysu z możliwością sterowania są używane do interaktywnego sterowania scenorysem.

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

Interaktywne kontrolowanie scenorysu przy użyciu kodu

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

Na poniższej liście przedstawiono metody, których można użyć do manipulowania Storyboard po rozpoczęciu:

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

Uwaga

Wszystkie interakcyjne akcje wykonywane na Clockobiekcie , a zatem także Storyboard na następnym znaczniku aparatu chronometrażu, które nastąpi wkrótce przed następnym renderowaniem. Jeśli na przykład użyjesz Seek metody , aby przejść do innego punktu w animacji, wartość właściwości nie zmienia się natychmiast, a wartość zmienia się na następnym znaczniku 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ą Storyboard obiektów można definiować animacje w obiekcie Style. Animowanie Storyboard za pomocą elementu w obiekcie Style jest podobne do użycia Storyboard w innym miejscu, z następującymi trzema wyjątkami:

  • Nie określasz elementu TargetName; element Storyboard zawsze jest przeznaczony dla elementu, do którego Style jest stosowany. Aby obiekty docelowe Freezable , należy użyć kierowania pośredniego. Aby uzyskać więcej informacji na temat kierowania pośredniego, zobacz sekcję Określanie kierowania pośredniego.

  • Nie można określić SourceName elementu dla elementu EventTrigger lub .Trigger

  • Nie można używać dynamicznych odwołań do zasobów ani wyrażeń powiązań danych do ustawiania Storyboard ani animacji wartości właściwości. Dzieje się tak, ponieważ wszystko wewnątrz elementu Style musi być bezpieczne wątkowo, a system chronometrażu musi FreezeStoryboard mieć obiekty, aby były bezpieczne wątkowo. Nie Storyboard można zamrozić elementu, jeśli oś czasu 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 zamrażania i innych Freezable funkcji, zobacz Omówienie obiektów zamrażalnych.

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

Przykład pokazujący sposób definiowania scenorysu w stylu, zobacz przykład Animowanie w stylu .

Animuj w ControlTemplate

Za pomocą Storyboard obiektów można definiować animacje w obiekcie ControlTemplate. Animowanie Storyboard za pomocą elementu w obiekcie ControlTemplate jest podobne do użycia Storyboard gdzie indziej, 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 jest przeznaczona dla elementu, do którego ControlTemplate jest stosowany.

  • Element dla SourceName obiektu EventTrigger lub Trigger może 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ązań danych do ustawiania Storyboard ani animacji wartości właściwości. Dzieje się tak, ponieważ wszystko wewnątrz elementu ControlTemplate musi być bezpieczne wątkowo, a system chronometrażu musi FreezeStoryboard mieć obiekty, aby były bezpieczne wątkowo. Nie Storyboard można zamrozić elementu, jeśli oś czasu 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 zamrażania i innych Freezable funkcji, zobacz Omówienie obiektów zamrażalnych.

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

Przykład pokazujący, jak zdefiniować scenorys w obiekcie ControlTemplate, zobacz przykład Animowanie w kontrolce ControlTemplate .

Animowanie zmiany wartości właściwości

W szablonach stylów i kontrolek można użyć obiektów Wyzwalacz, aby rozpocząć scenorys po zmianie właściwości. Przykłady można znaleźć w temacie Trigger an Animation When a Property Value Changes and Animate in a ControlTemplate (Wyzwalanie animacji po zmianie wartości właściwości i animowanie w kontrolce ControlTemplate).

Animacje stosowane przez obiekty właściwości Trigger zachowują się w bardziej złożony sposób niż EventTrigger animacje lub animacje zaczęły korzystać z Storyboard metod. Są one "przekazywanie" z animacjami zdefiniowanymi przez inne Trigger obiekty, ale tworzą animacje z wyzwalanymi metodami EventTrigger i .

Zobacz też