Vue d'ensemble des storyboards

Cette rubrique montre comment utiliser des Storyboard objets pour organiser et appliquer des animations. Il décrit comment manipuler Storyboard des objets de manière interactive et décrit la syntaxe de ciblage des propriétés indirectes.

Prérequis

Pour comprendre cette rubrique, vous devez connaître les différents types d’animations et leurs fonctions de base. Pour une introduction à l’animation, consultez Vue d’ensemble de l’animation. Vous devez également savoir comment utiliser les propriétés jointes. Pour plus d’informations sur les propriétés jointes, consultez Vue d’ensemble des propriétés jointes.

Présentation d’un storyboard

Les animations ne sont pas le seul type utile de chronologie. D’autres classes de chronologie sont fournies pour vous aider à organiser des jeux de chronologies et à appliquer des chronologies aux propriétés. Les chronologies de conteneur dérivent de la TimelineGroup classe, et incluent ParallelTimeline et Storyboard.

Il Storyboard s’agit d’un type de chronologie de conteneur qui fournit des informations de ciblage pour les chronologies qu’il contient. Un storyboard peut contenir n’importe quel type, Timeliney compris d’autres chronologies et animations de conteneur. Storyboard les objets vous permettent de combiner des chronologies qui affectent une variété d’objets et de propriétés dans une arborescence de chronologie unique, ce qui facilite l’organisation et le contrôle des comportements de minutage complexes. Par exemple, supposons que vous souhaitiez disposer d’un bouton qui effectue les trois opérations suivantes.

  • Développer et changer de couleur lorsque l’utilisateur sélectionne le bouton.

  • Réduire puis revenir à la taille normale lorsque l’utilisateur clique dessus.

  • Réduire et atténuer l’opacité en la définissant sur 50 % lorsque le bouton est désactivé.

Dans ce cas, vous avez plusieurs jeux d’animations qui s’appliquent au même objet, et vous souhaitez les jouer à différents moments, en fonction de l’état du bouton. Storyboard les objets vous permettent d’organiser les animations et de les appliquer dans des groupes à un ou plusieurs objets.

Où pouvez-vous utiliser un storyboard ?

Un Storyboard peut être utilisé pour animer les propriétés de dépendance des classes animatables (pour plus d’informations sur ce qui rend une classe animatable, consultez la vue d’ensemble de l’animation). Toutefois, étant donné que le storyboarding est une fonctionnalité au niveau de l’infrastructure, l’objet doit appartenir à un NameScope FrameworkElement ou un FrameworkContentElement.

Par exemple, vous pouvez utiliser une Storyboard commande pour effectuer les opérations suivantes :

Toutefois, vous n’avez pas pu utiliser un Storyboard pour animer un SolidColorBrush qui n’a pas inscrit son nom auprès d’un FrameworkElement ou , ou FrameworkContentElementn’a pas été utilisé pour définir une propriété d’un FrameworkElement ou FrameworkContentElement.

Comment appliquer des animations avec une table de montage séquentiel

Pour utiliser un Storyboard pour organiser et appliquer des animations, vous ajoutez les animations en tant que chronologies enfants du Storyboard. La Storyboard classe fournit les Storyboard.TargetName propriétés jointes et Storyboard.TargetProperty les propriétés jointes. Vous définissez ces propriétés sur une animation pour spécifier sa propriété et son objet cibles.

Pour appliquer des animations à leurs cibles, vous commencez à Storyboard utiliser une action de déclencheur ou une méthode. En XAML, vous utilisez un BeginStoryboard objet avec un EventTrigger, Triggerou DataTrigger. Dans le code, vous pouvez également utiliser la Begin méthode.

Le tableau suivant présente les différents endroits où chaque Storyboard technique de début est prise en charge : par instance, style, modèle de contrôle et modèle de données. « Par instance » fait référence à la technique consistant à appliquer une animation ou une table de montage séquentiel directement aux instances d’un objet, plutôt qu’à un style, un modèle de contrôle ou un modèle de données.

La table de montage séquentiel démarre à l’aide de… Par instance Style Modèle de contrôle Modèle de données Exemple
BeginStoryboard et un EventTrigger Oui Oui Oui Oui Animer une propriété à l’aide d’une table de montage séquentiel
BeginStoryboard et une propriété Trigger Non Oui Oui Oui Déclencher une animation en cas de modification d’une valeur de propriété
BeginStoryboard et une propriété MultiTrigger Non Oui Oui Oui Exemple de classe MultiTrigger
BeginStoryboard et un DataTrigger Non Oui Oui Oui Comment : déclencher une animation en cas de modification de données
BeginStoryboard et un MultiDataTrigger Non Oui Oui Oui Exemple de classe MultiDataTrigger
Méthode Begin Oui No Non Non Animer une propriété à l’aide d’une table de montage séquentiel

L’exemple suivant utilise un Storyboard pour animer l’élément Width Rectangle et l’un Color d’un SolidColorBrush utilisé pour peindre cela 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;
        }
    }
}

Les sections suivantes décrivent plus en détail les TargetName propriétés jointes et TargetProperty les propriétés jointes.

Ciblage des éléments d’infrastructure, des éléments de contenu d’infrastructure et des éléments Freezables

Dans la section précédente, il était mentionné que, pour qu’une animation trouve sa cible, elle devait connaître la propriété et le nom de la cible à animer. La spécification de la propriété à animer est directement définie TargetProperty avec le nom de la propriété à animer. Vous spécifiez le nom de l’objet dont vous souhaitez animer la propriété en définissant la Storyboard.TargetName propriété sur l’animation.

Attention

Bien que vous puissiez utiliser la Target propriété pour établir une liaison directe à un objet en guise d’alternative, TargetNameelle n’est pas sérialisable. Il n’est pas garanti que l’objet Target puisse être correctement référencé en XAML.

Pour que la TargetName propriété fonctionne, l’objet ciblé doit avoir un nom. L’affectation d’un nom à un FrameworkElement ou à un FrameworkContentElement en XAML est différente de l’affectation d’un nom à un Freezable objet.

Les éléments d’infrastructure sont ces classes qui héritent de la FrameworkElement classe. Exemples d’éléments de framework : Window, DockPanel, Buttonet Rectangle. Essentiellement, tous les contrôles, panneaux et fenêtres sont des éléments. Les éléments de contenu du framework sont ces classes qui héritent de la FrameworkContentElement classe. Exemples d’éléments de contenu de framework incluent FlowDocument et Paragraph. Si vous ne savez pas si un type est un élément d’infrastructure ou un élément de contenu d’infrastructure, vérifiez s’il possède une propriété Nom. Si c’est le cas, il s’agit probablement d’un élément d’infrastructure ou d’un élément de contenu d’infrastructure. Pour vous en assurer, vérifiez la section Inheritance Hierarchy (Hiérarchie d’héritage) de sa page de type.

Pour activer le ciblage d’un élément de framework ou d’un élément de contenu d’infrastructure en XAML, vous définissez sa Name propriété. Dans le code, vous devez également utiliser la RegisterName méthode pour inscrire le nom de l’élément auprès de l’élément pour lequel vous avez créé un NameScope.

L’exemple suivant, extrait de l’exemple précédent, affecte le nom MyRectangle a Rectangle, un type de 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);

Une fois qu’un nom a été assigné, vous pouvez animer une propriété de cet élément.

<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 les types sont ces classes qui héritent de la Freezable classe. Exemples d’inclure Freezable SolidColorBrush, RotateTransformet GradientStop.

Pour activer le ciblage d’une Freezable animation en XAML, vous utilisez la directive x :Name pour lui attribuer un nom. Dans le code, vous utilisez la RegisterName méthode pour inscrire son nom auprès de l’élément pour lequel vous avez créé un NameScope.

L’exemple suivant affecte un nom à un Freezable objet.

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

L’objet peut ensuite être ciblé par une animation.

<ColorAnimation 
  Storyboard.TargetName="MySolidColorBrush"
  Storyboard.TargetProperty="Color"
  From="Blue" To="Red" Duration="0:0:1" />  
Storyboard.SetTargetName(myColorAnimation, "MySolidColorBrush");
Storyboard.SetTargetProperty(myColorAnimation,
    new PropertyPath(SolidColorBrush.ColorProperty));

Storyboard les objets utilisent des étendues de nom pour résoudre la TargetName propriété. Pour plus d’informations sur les portées de nom WPF, consultez Portées de nom XAML WPF. Si la TargetName propriété est omise, l’animation cible l’élément sur lequel il est défini, ou, dans le cas des styles, l’élément de style.

Parfois, un nom ne peut pas être affecté à un Freezable objet. Par exemple, si une Freezable ressource est déclarée comme ressource ou utilisée pour définir une valeur de propriété dans un style, elle ne peut pas être nommée. Comme il n’a pas de nom, il ne peut pas être ciblé directement, mais peut l’être indirectement. Les sections suivantes décrivent comment utiliser le ciblage indirect.

Ciblage indirect

Il est parfois Freezable impossible de cibler directement par une animation, par exemple lorsque l’objet Freezable est déclaré en tant que ressource ou utilisé pour définir une valeur de propriété dans un style. Dans ces cas, même si vous ne pouvez pas le cibler directement, vous pouvez toujours animer l’objet Freezable . Au lieu de définir la TargetName propriété avec le nom du Freezable, vous lui donnez le nom de l’élément auquel le Freezable « appartient ». Par exemple, un SolidColorBrush élément de rectangle utilisé pour définir l’élément Fill rectangle appartient à ce rectangle. Pour animer le pinceau, vous devez définir les animations TargetProperty avec une chaîne de propriétés qui commence à la propriété de l’élément framework ou de l’élément de contenu du framework utilisé Freezable pour définir et se terminer par la Freezable propriété à animer.

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

Notez que, si le Freezable clone est figé, un clone sera fait et que ce clone sera animé. Lorsque cela se produit, la propriété de l’objet HasAnimatedProperties d’origine continue de retourner false, car l’objet d’origine n’est pas réellement animé. Pour plus d’informations sur le clonage, consultez Vue d’ensemble des objets Freezable.

Notez également que, lorsque vous utilisez le ciblage de propriété indirect, il est possible de cibler des objets qui n’existent pas. Par exemple, vous pouvez supposer que le Background bouton particulier a été défini avec un SolidColorBrush bouton et essayer d’animer sa couleur, quand en fait un LinearGradientBrush a été utilisé pour définir l’arrière-plan du bouton. Dans ces cas, aucune exception n’est levée ; l’animation n’a pas d’effet visible, car LinearGradientBrush elle ne réagit pas aux modifications apportées à la Color propriété.

Les sections suivantes décrivent plus en détail la syntaxe de ciblage de propriété indirect.

Ciblage indirect d’une propriété d’un élément Freezable en XAML

Pour cibler une propriété d’un freezable en XAML, utilisez la syntaxe suivante.

Syntaxe des propriétés
ElementPropertyName . FreezablePropertyName

Where

  • ElementPropertyName est la propriété de l’élément Freezable FrameworkElement utilisé pour définir et

  • FreezablePropertyName est la propriété de l’animation Freezable .

Le code suivant montre comment animer l’élément Color SolidColorBrush utilisé pour définir l’élément Fill rectangle.

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

Vous devez parfois cibler un élément Freezable contenu dans une collection ou un tableau.

Pour cibler un élément Freezable contenu dans une collection, vous utilisez la syntaxe de chemin d’accès suivante.

Syntaxe du chemin
ElementPropertyName .Children[ CollectionIndex ]. FreezablePropertyName

CollectionIndex est l’index de l’objet dans son tableau ou sa collection.

Par exemple, supposons qu’un rectangle a une TransformGroup ressource appliquée à sa RenderTransform propriété et que vous souhaitez animer l’une des transformations qu’il contient.

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

Le code suivant montre comment animer la Angle propriété de l’exemple RotateTransform précédent.

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

Ciblage indirect d’une propriété d’un élément Freezable dans le code

Dans le code, vous créez un PropertyPath objet. Lorsque vous créez le PropertyPath, vous spécifiez un Path et PathParameters.

Pour créer, vous créez PathParametersun tableau de type DependencyProperty qui contient une liste de champs d’identificateur de propriété de dépendance. Le premier champ d’identificateur correspond à la propriété du FrameworkElement ou FrameworkContentElement à celui Freezable utilisé pour définir. Le champ d’identificateur suivant représente la propriété de la Freezable cible. Considérez-le comme une chaîne de propriétés qui connecte l’objet Freezable FrameworkElement .

Voici un exemple de chaîne de propriétés de dépendance qui cible l’un Color SolidColorBrush des éléments utilisés pour définir l’élément Fill rectangle.

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

Vous devez également spécifier un Path. A Path est un String qui indique comment Path interpréter son PathParameters. Il utilise la syntaxe suivante.

Syntaxe du chemin d’accès aux propriétés
(OwnerPropertyArrayIndex ).( FreezablePropertyArrayIndex )

Where

  • OwnerPropertyArrayIndex est l’index du DependencyProperty tableau qui contient l’identificateur de la propriété de l’objet FrameworkElement utilisée Freezable pour définir et

  • FreezablePropertyArrayIndex est l’index du DependencyProperty tableau qui contient l’identificateur de propriété à cibler.

L’exemple suivant montre les Path éléments qui accompagnent l’exemple PathParameters défini dans l’exemple précédent.

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

L’exemple suivant combine le code dans les exemples précédents pour animer l’élément Color SolidColorBrush utilisé pour définir l’élément Fill rectangle.


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

Vous devez parfois cibler un élément Freezable contenu dans une collection ou un tableau. Par exemple, supposons qu’un rectangle a une TransformGroup ressource appliquée à sa RenderTransform propriété et que vous souhaitez animer l’une des transformations qu’il contient.

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

Pour cibler un Freezable contenu dans une collection, vous utilisez la syntaxe de chemin d’accès suivante.

Syntaxe du chemin
(OwnerPropertyArrayIndex ).( CollectionChildrenPropertyArrayIndex ) [ CollectionIndex ].( FreezablePropertyArrayIndex )

CollectionIndex est l’index de l’objet dans son tableau ou sa collection.

Pour cibler la Angle propriété du RotateTransform, la deuxième transformation dans le TransformGroup, vous devez utiliser les éléments suivants Path et 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);

L’exemple suivant montre le code complet permettant d’animer un Angle RotateTransform contenu dans un 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);

Ciblage indirect avec un élément Freezable comme point de départ

Les sections précédentes ont décrit comment cibler indirectement un en Freezable commençant par une FrameworkElement ou FrameworkContentElement en créant une chaîne de propriétés vers une Freezable sous-propriété. Vous pouvez également utiliser un Freezable point de départ et cibler indirectement l’une de ses Freezable sous-propriétés. Une restriction supplémentaire s’applique lors de l’utilisation d’un Freezable point de départ pour le ciblage indirect : le début Freezable et chaque Freezable entre celui-ci et la sous-propriété ciblée indirectement ne doivent pas être figés.

Contrôle interactif d’une table de montage séquentiel en XAML

Pour démarrer un storyboard dans XAML (Extensible Application Markup Language), vous utilisez une BeginStoryboard action de déclencheur. BeginStoryboard distribue les animations aux objets et aux propriétés qu’ils animent et démarre le storyboard. (Pour plus d’informations sur ce processus, consultez le Vue d’ensemble du système d’animation et de minutage.) Si vous attribuez un BeginStoryboard nom en spécifiant sa Name propriété, vous le rendez un storyboard contrôlable. Vous pouvez ensuite contrôler interactivement la table de montage séquentiel après son démarrage. Vous trouverez ci-dessous une liste d’actions de table de montage séquentiel contrôlable à utiliser avec des déclencheurs d’événements pour contrôler une table de montage séquentiel.

Dans l’exemple suivant, les actions de table de montage séquentiel contrôlable servent à contrôler interactivement une table de montage séquentiel.

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

Contrôle interactif d’une table de montage séquentiel avec du code

Les exemples précédents ont montré comment animer à l’aide d’actions de déclencheur. Dans le code, vous pouvez également contrôler un storyboard à l’aide de méthodes interactives de la Storyboard classe. Pour qu’un Storyboard élément soit interactif dans le code, vous devez utiliser la surcharge appropriée de la méthode du Begin storyboard et spécifier true pour le rendre contrôlable. Pour plus d’informations, consultez la Begin(FrameworkElement, Boolean) page.

La liste suivante montre les méthodes qui peuvent être utilisées pour manipuler une Storyboard fois qu’elle a démarré :

L’avantage d’utiliser ces méthodes est que vous n’avez pas besoin de créer Trigger ou TriggerAction d’objets ; vous avez simplement besoin d’une référence à l’élément contrôlable Storyboard que vous souhaitez manipuler.

Remarque

Toutes les actions interactives effectuées sur un Clock, et donc également sur une Storyboard se produira lors de la prochaine cycles du moteur de minutage qui se produira peu avant le rendu suivant. Par exemple, si vous utilisez la Seek méthode pour passer à un autre point dans une animation, la valeur de propriété ne change pas instantanément, au lieu de cela, la valeur change lors de la graduation suivante du moteur de minutage.

L’exemple suivant montre comment appliquer et contrôler des animations à l’aide des méthodes interactives de la Storyboard classe.

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

Animer dans un objet Style

Vous pouvez utiliser des Storyboard objets pour définir des animations dans un Style. L’animation avec un Storyboard dans un Style est similaire à l’utilisation d’un Storyboard autre emplacement, avec les trois exceptions suivantes :

  • Vous ne spécifiez pas un TargetName; l’élément Storyboard cible toujours l’élément auquel il Style est appliqué. Pour cibler Freezable des objets, vous devez utiliser le ciblage indirect. Pour plus d’informations sur le ciblage indirect, consultez la section Ciblage indirect.

  • Vous ne pouvez pas spécifier un SourceName pour un EventTrigger ou un Trigger.

  • Vous ne pouvez pas utiliser de références de ressources dynamiques ou d’expressions de liaison de données pour définir ou animation des Storyboard valeurs de propriété. C’est parce que tout à l’intérieur d’un Style doit être thread-safe, et le système de minutage doit FreezeStoryboard les objets pour les rendre thread-safe. Impossible Storyboard de figer s’il ou ses chronologies enfants contiennent des références de ressources dynamiques ou des expressions de liaison de données. Pour plus d’informations sur le gel et d’autres Freezable fonctionnalités, consultez la vue d’ensemble des objets freezables.

  • En XAML, vous ne pouvez pas déclarer de gestionnaires d’événements pour Storyboard ou d’événements d’animation.

Pour obtenir un exemple montrant comment définir une table de montage séquentiel dans un style, consultez l’exemple Animer dans un style.

Animer dans un objet ControlTemplate

Vous pouvez utiliser des Storyboard objets pour définir des animations dans un ControlTemplate. L’animation avec un Storyboard dans un ControlTemplate est similaire à l’utilisation d’un Storyboard autre emplacement, avec les deux exceptions suivantes :

  • Le TargetName seul objet peut faire référence aux objets enfants du ControlTemplate. Si TargetName elle n’est pas spécifiée, l’animation cible l’élément auquel l’application ControlTemplate est appliquée.

  • Le SourceName pour un EventTrigger ou un Trigger peut uniquement faire référence aux objets enfants de l’objet ControlTemplate.

  • Vous ne pouvez pas utiliser de références de ressources dynamiques ou d’expressions de liaison de données pour définir ou animation des Storyboard valeurs de propriété. C’est parce que tout à l’intérieur d’un ControlTemplate doit être thread-safe, et le système de minutage doit FreezeStoryboard les objets pour les rendre thread-safe. Impossible Storyboard de figer s’il ou ses chronologies enfants contiennent des références de ressources dynamiques ou des expressions de liaison de données. Pour plus d’informations sur le gel et d’autres Freezable fonctionnalités, consultez la vue d’ensemble des objets freezables.

  • En XAML, vous ne pouvez pas déclarer de gestionnaires d’événements pour Storyboard ou d’événements d’animation.

Pour obtenir un exemple montrant comment définir un storyboard dans un ControlTemplate, consultez l’exemple Animate dans un ControlTemplate .

Animer en cas de modification d’une valeur de propriété

Dans les styles et les modèles de contrôle, vous pouvez utiliser des objets Trigger pour démarrer une table de montage séquentiel en cas de modification d’une propriété. Pour obtenir des exemples, consultez Déclencher une animation en cas de modification d’une valeur de propriété et Effectuer une animation dans un ControlTemplate.

Les animations appliquées par les objets de propriété Trigger se comportent de manière plus complexe que EventTrigger les animations ou les animations démarrées à l’aide Storyboard de méthodes. Ils « transfert » avec des animations définies par d’autres Trigger objets, mais composent avec et des EventTrigger animations déclenchées par des méthodes.

Voir aussi