Przegląd Scenorysy

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

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. Podane 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ą od TimelineGroup klasy i obejmują ParallelTimeline i Storyboard .

A Storyboard to typ osi czasu kontenera, który zawiera informacje dotyczące określania docelowych osi czasu, które zawiera. Scenorys może zawierać dowolnego typu, w Timeline tym inne osie czasu kontenera i animacje. Storyboard obiekty umożliwiają łączenie osi czasu, które mają wpływ na wiele obiektów i właściwości na jedno drzewo osi czasu, co ułatwia organizowanie i kontrolowanie złożonych zachowań chronometrażu. Załóżmy na przykład, że chcesz, aby przycisk przerobił te trzy rzeczy.

  • Powiększ i Zmień kolor, gdy użytkownik wybierze przycisk.

  • Po kliknięciu Zmniejsz rozmiar do oryginalnego rozmiaru.

  • Zmniejsz i zwiększ poziom przezroczystości do 50 procent, gdy zostanie on wyłączony.

W takim przypadku istnieje wiele zestawów animacji, które mają zastosowanie do tego samego obiektu i chcesz odtwarzać w różnych godzinach zależnie od stanu przycisku. Storyboard obiekty umożliwiają organizowanie animacji i stosowanie ich w grupach do co najmniej jednego obiektu.

Gdzie można używać scenorysu

A Storyboard może służyć do animowania właściwości zależności klas animowanych (Aby uzyskać więcej informacji na temat tego, co ułatwia animowanie klasy, zobacz Omówienie animacji). Jednak ponieważ scenorysowanie jest funkcją poziomu platformy, obiekt musi należeć do NameScope FrameworkElement lub FrameworkContentElement .

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

Nie można jednak użyć Storyboard do animacji SolidColorBrush , która nie zarejestrowała jego nazwy z FrameworkElement lub lub FrameworkContentElement nie została użyta do ustawienia właściwości FrameworkElement lub FrameworkContentElement .

Jak zastosować animacje z Scenorysem

Aby użyć programu Storyboard do organizowania i stosowania animacji, należy dodać animacje jako podrzędne osie czasu Storyboard . StoryboardKlasa zawiera Storyboard.TargetName Storyboard.TargetProperty właściwości i dołączone. Te właściwości można ustawić dla animacji, aby określić jej obiekt docelowy i właściwość.

Aby zastosować animacje do ich elementów docelowych, należy rozpocząć Storyboard Korzystanie z akcji wyzwalacza lub metody. W programie XAML używasz BeginStoryboard obiektu z EventTrigger , Trigger lub 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 BEGIN: na wystąpienie, styl, szablon formantu i szablon danych. "Na wystąpienie" odnosi się do techniki stosowania animacji lub scenorysu bezpośrednio do wystąpień obiektu, a nie w stylu, szablonie kontrolki lub szablonie danych.

Trwa Rozpoczynanie korzystania z scenorysu... 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 wielowyzwalaczowej
BeginStoryboard i a DataTrigger Nie Tak Tak Tak Instrukcje: wyzwalanie animacji w przypadku zmiany 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 Storyboard do animowania Width Rectangle elementu i obiektu Color SolidColorBrush używanego do malowania 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 i TargetProperty dołączono właściwości bardziej szczegółowo.

Elementy platformy docelowej, elementy zawartości struktury i obiektów Freezable platformie

W poprzedniej sekcji wymienionej przez, aby uzyskać animację, aby znaleźć jej obiekt docelowy, musi znać nazwę obiektu docelowego i właściwość do animacji. Określanie właściwości do animacji jest proste do przodu: po prostu ustaw TargetProperty nazwę właściwości do animacji. Należy określić nazwę obiektu, którego właściwość ma być animowana przez ustawienie Storyboard.TargetName właściwości animacji.

Przestroga

Można użyć Target właściwości, aby powiązać bezpośrednio z obiektem jako alternatywę dla TargetName , nie jest możliwe do serializacji. Nie ma gwarancji, że Target obiekt może być prawidłowo przywoływany w języku XAML.

Aby TargetName Właściwość działała, obiekt Target musi mieć nazwę. Przypisanie nazwy do FrameworkElement lub FrameworkContentElement w XAML jest inne niż przypisanie nazwy do Freezable obiektu.

Elementy struktury są tymi klasami, które dziedziczą z FrameworkElement klasy. Przykłady elementów struktury obejmują Window , DockPanel , Button , i Rectangle . Zasadniczo wszystkie okna, panele i kontrolki są elementami. Elementy zawartości struktury są tymi klasami, które dziedziczą z FrameworkContentElement klasy. Przykłady elementów zawartości struktury obejmują FlowDocument i Paragraph . Jeśli nie masz pewności, czy typem jest element struktury lub element zawartości platformy, sprawdź, czy ma on Właściwość Name. Jeśli tak, jest to prawdopodobnie element struktury lub element zawartości platformy. Aby się upewnić, sprawdź sekcję Hierarchia dziedziczenia na stronie Typ.

Aby włączyć Określanie wartości docelowej elementu Framework lub elementu zawartości Framework w XAML , należy ustawić jego Name Właściwość. W kodzie, należy również użyć RegisterName metody do zarejestrowania nazwy elementu z elementem, dla którego został utworzony NameScope .

Poniższy przykład, który został pobrany z poprzedniego przykładu, przypisuje nazwę MyRectangle a Rectangle , 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 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 są tymi klasami, które dziedziczą z Freezable klasy. Przykłady Freezable include SolidColorBrush , RotateTransform i GradientStop .

Aby włączyć Określanie wartości docelowej Freezable przez animację w programie XAML , należy użyć dyrektywy x:Name w celu przypisania jej nazwy. W kodzie, używasz RegisterName metody do rejestrowania jej nazwy z elementem, dla którego został utworzony 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 wskazywany 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 Zakresy nazw WPF. Jeśli TargetName Właściwość zostanie pominięta, animacja odwołuje się do elementu, w którym jest zdefiniowany, lub, w przypadku stylów, elementu style.

Czasami nazwa nie może być przypisana do Freezable obiektu. Na przykład jeśli obiekt Freezable jest zadeklarowany jako zasób lub używany do ustawiania wartości właściwości w stylu, nie może mieć nazwy. Ponieważ nie ma nazwy, nie może być wskazywany bezpośrednio, ale może być wskazywany pośrednio. W poniższych sekcjach opisano sposób używania pośredniego określania wartości docelowej.

Pośrednie Określanie wartości docelowej

Istnieją przypadki, w których Freezable nie mogą być wskazywane bezpośrednio przez animację, na przykład gdy Freezable jest zadeklarowany jako zasób lub używany do ustawiania wartości właściwości w stylu. W takich przypadkach, mimo że nie można kierować do niego bezpośrednio, można nadal animować Freezable obiekt. Zamiast ustawić TargetName Właściwość o nazwie Freezable , nadaj jej nazwę elementu, do którego Freezable należy ". Na przykład, SolidColorBrush używany do ustawiania Fill elementu prostokąta należy do tego prostokąta. Aby animować pędzla, należy ustawić animację TargetProperty z łańcuchem właściwości, które zaczynają się od właściwości elementu Framework lub elementu zawartości platformy, który Freezable został użyty do ustawienia i zakończenia Freezable właściwości do animacji.

<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 jest zablokowany, zostanie utworzony klon, a klon zostanie animowany. Gdy tak się stanie, właściwość oryginalnego obiektu HasAnimatedProperties będzie nadal zwracana false , ponieważ oryginalny obiekt nie jest w rzeczywistości animowany. Aby uzyskać więcej informacji na temat klonowania, zobacz Omówienie obiektów Freezable.

Należy również zauważyć, że w przypadku używania określania wartości docelowej właściwości pośredniej możliwe jest obiekty docelowe, które nie istnieją. Na przykład można założyć, że Background określony przycisk został ustawiony z SolidColorBrush i próbować animować jego kolor, gdy w rzeczywistości LinearGradientBrush użyto do ustawienia tła przycisku. W takich przypadkach nie jest zgłaszany żaden wyjątek; Animacja nie może mieć widocznego efektu, ponieważ nie LinearGradientBrush reaguje na zmiany Color właściwości.

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

Pośrednie Określanie wartości właściwości Freezable w języku XAML

Aby określić właściwość elementu Freezable w, należy XAML użyć następującej składni.

ElementPropertyName . FreezablePropertyName

Lokalizacja

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

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

Poniższy kod pokazuje, jak animować wartość Color SolidColorBrush użytą do ustawienia 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 musisz wskazać Freezable zawarty w kolekcji lub tablicy.

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

ElementPropertyName .Children[ CollectionIndex ]. FreezablePropertyName

Gdzie CollectionIndex jest indeksem obiektu w jego tablicy lub kolekcji.

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

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

Poniższy kod przedstawia sposób animowania Angle właściwości RotateTransform pokazanej 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średnie Określanie wartości docelowej właściwości Freezable w kodzie

W kodzie, tworzysz PropertyPath obiekt. Podczas tworzenia należy PropertyPath określić Path i PathParameters .

Aby utworzyć PathParameters , należy utworzyć tablicę typu DependencyProperty , która zawiera listę pól identyfikatora właściwości zależności. Pole pierwszego identyfikatora jest właściwością FrameworkElement lub FrameworkContentElement , która Freezable jest używana do ustawiania. Następne pole identyfikatora reprezentuje właściwość Freezable elementu docelowego. Należy traktować go jako łańcuch właściwości, które łączą Freezable się z FrameworkElement obiektem.

Poniżej znajduje się przykład łańcucha właściwości zależności, który jest Color przeznaczony dla elementu typu prostokąt, który jest celem obiektu SolidColorBrush Fill .

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

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

(OwnerPropertyArrayIndex ).( FreezablePropertyArrayIndex)

Lokalizacja

  • OwnerPropertyArrayIndex jest indeksem tablicy zawierającej DependencyProperty Identyfikator FrameworkElement właściwości obiektu, który Freezable jest używany do ustawiania, i

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

W poniższym przykładzie pokazano, Path że towarzyszy PathParameters zdefiniowanej 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 w celu animowania obiektu Color SolidColorBrush używanego 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 musisz wskazać Freezable zawarty w kolekcji lub tablicy. Załóżmy na przykład, że prostokąt ma TransformGroup zastosowany zasób do jego RenderTransform właściwości, i chcesz animować jedną z przekształceń, która zawiera.

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

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

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

Gdzie CollectionIndex jest indeksem obiektu w jego tablicy lub kolekcji.

Aby określić Angle Właściwość RotateTransform , drugie przekształcenie w TransformGroup , należy użyć następujących elementów Path 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);

Poniższy przykład pokazuje kompletny kod animacji elementu Angle RotateTransform zawartego w elemencie 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 kierowanie przy użyciu Freezable jako punktu początkowego

W poprzednich sekcjach opisano, jak pośrednio skierować obiekt docelowy Freezable , rozpoczynając od FrameworkElement lub FrameworkContentElement i tworząc łańcuch właściwości do Freezable Właściwości podrzędnej. Można również użyć Freezable jako punktu początkowego i pośrednio docelowej jednej z jego Freezable właściwości podrzędnych. Jedno dodatkowe ograniczenie ma zastosowanie w przypadku używania Freezable jako punktu początkowego do pośredniego określania docelowej: początku Freezable i co Freezable między nim a bezpośrednią podklasą docelową nie może być zablokowany.

Interaktywna kontrola scenorysu w języku XAML

Aby rozpocząć scenorys w programie 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 są animowane, i uruchamia scenorys. (Aby uzyskać szczegółowe informacje o tym procesie, zobacz Omówienie animacji i systemu chronometrażu). W przypadku nadania BeginStoryboard nazwy przez określenie jej Name właściwości można ją przetworzyć w scenorysie. Następnie możesz interaktywnie kontrolować scenorys po jego uruchomieniu. Poniżej znajduje się lista kontrolowanych akcji scenorysu, które są używane z wyzwalaczami zdarzeń do kontrolowania scenorysu.

W poniższym przykładzie akcje z kontrolowanego scenorysu 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>

Interaktywna kontrola scenorysu przy użyciu kodu

Poprzednie przykłady pokazują, jak animować przy użyciu akcji wyzwalacza. W kodzie można również kontrolować scenorys przy użyciu interaktywnych metod Storyboard klasy. Aby Storyboard można było interaktywnie wprowadzić kod, należy użyć odpowiedniego przeciążenia metody scenorysu Begin i określić, true Aby umożliwić jej możliwość kontrolowania. 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:

Zalety korzystania z tych metod polegają na tym, że nie musisz Trigger tworzyć TriggerAction obiektów lub obiekty; wystarczy tylko do kontroli, Storyboard którą chcesz manipulować.

Uwaga

Wszystkie interaktywne akcje wykonywane w systemie Clock , a tym samym również w Storyboard odniesieniu do następnego taktu aparatu czasu, które będą miały miejsce wkrótce przed następnym renderowaniem. Na przykład, jeśli używasz Seek metody do przechodzenia do innego punktu w animacji, wartość właściwości nie zmienia się natychmiast, a wartość zmienia się w następnym taktie aparatu czasu.

Poniższy przykład pokazuje, jak zastosować 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

Można używać Storyboard obiektów do definiowania animacji w Style . Animowanie przy użyciu Storyboard w Style i jest podobne do użycia w Storyboard innym miejscu, z następującymi trzema wyjątkami:

  • Nie określono TargetName elementu; zawsze jest to Storyboard element, do którego Style zastosowano. Aby obiekty docelowe były obiektami docelowymi Freezable , 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ę Określanie wartości docelowej .

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

  • Nie można używać odwołań do zasobów dynamicznych ani wyrażeń powiązań danych do ustawiania Storyboard lub animacji wartości właściwości. Dzieje się tak dlatego, że wszystko wewnątrz elementu Style musi być bezpieczne wątkowo, a system chronometrażu musi Freeze Storyboard obiekty, aby uczynić je bezpiecznym wątkowo. StoryboardNie można zamrozić, jeśli lub jego podrzędne osie czasu zawierają odwołania do zasobów dynamicznych lub wyrażenia powiązań danych. Aby uzyskać więcej informacji na temat zamrażania i innych Freezable funkcji, zobacz Omówienie obiektów Freezable.

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

Przykład przedstawiający sposób definiowania scenorysu w stylu można znaleźć w przykładzie animacji w stylu .

Animuj w ControlTemplate

Można używać Storyboard obiektów do definiowania animacji w ControlTemplate . Animowanie przy użyciu Storyboard w programie ControlTemplate jest podobne do użycia w Storyboard innym miejscu, z następującymi dwoma wyjątkami:

  • TargetNameMoże odwoływać się tylko do obiektów podrzędnych obiektu ControlTemplate . Jeśli TargetName nie jest określony, animacja jest przeznaczona dla elementu, do którego ControlTemplate jest stosowana.

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

  • Nie można używać odwołań do zasobów dynamicznych ani wyrażeń powiązań danych do ustawiania Storyboard lub animacji wartości właściwości. Dzieje się tak dlatego, że wszystko wewnątrz elementu ControlTemplate musi być bezpieczne wątkowo, a system chronometrażu musi Freeze Storyboard obiekty, aby uczynić je bezpiecznym wątkowo. StoryboardNie można zamrozić, jeśli lub jego podrzędne osie czasu zawierają odwołania do zasobów dynamicznych lub wyrażenia powiązań danych. Aby uzyskać więcej informacji na temat zamrażania i innych Freezable funkcji, zobacz Omówienie obiektów Freezable.

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

Aby zapoznać się z przykładem dotyczącym definiowania scenorysu w ControlTemplate , zobacz Animuj w ControlTemplate przykładzie.

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

W stylach i szablonach formantów można używać obiektów wyzwalaczy do uruchamiania scenorysu podczas zmiany właściwości. Aby zapoznać się z przykładami, zobacz wyzwalanie animacji, gdy wartość właściwości zmieni się i Animuj w ControlTemplate.

Animacje stosowane przez Trigger obiekty właściwości zachowują się w sposób bardziej skomplikowany niż EventTrigger animacje i animacje rozpoczęte przy użyciu Storyboard metod. Są one "przekazanie" z animacjami zdefiniowanymi przez inne Trigger obiekty, ale tworzą animacje z użyciem EventTrigger metody i wyzwalane metodami.

Zobacz też