Partager via


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.

Conditions préalables

Pour comprendre cette rubrique, vous devez être familiarisé avec les différents types d’animations et leurs fonctionnalités de base. Pour une présentation de l’animation, consultez la 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 la vue d’ensemble des propriétés jointes.

Qu'est-ce qu'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 ensembles 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.

Storyboard est un type de chronologie conteneur qui fournit des informations de ciblage pour les chronologies qu’il contient. Un Storyboard peut contenir n'importe quel type d'élément Timeline, y compris d'autres lignes de temps 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 un bouton qui effectue ces trois opérations.

  • Augmentez et modifiez la couleur lorsque l’utilisateur sélectionne le bouton.

  • Rétrécissez puis reprenez sa taille d'origine lorsqu'on clique dessus.

  • Réduisez et passez à 50 % d’opacité lorsqu’il devient désactivé.

Dans ce cas, vous avez plusieurs ensembles d'animations qui s'appliquent au même objet, et vous souhaitez les jouer à des moments différents, 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 à l’un des NameScope, FrameworkElement ou 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 FrameworkContentElement, ou qui n’a pas été utilisé pour définir une propriété d’un FrameworkElement ou FrameworkContentElement.

Comment appliquer des animations avec un storyboard

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

Pour appliquer des animations à leurs cibles, vous commencez par Storyboard utiliser une action de déclenchement 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 d’application d’une animation ou d’un storyboard directement aux instances d’un objet, plutôt que dans un style, un modèle de contrôle ou un modèle de données.

On commence le storyboard en utilisant… 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’un storyboard
BeginStoryboard et une propriété Trigger Non Oui Oui Oui Déclencher une animation lorsqu’une valeur de propriété change
BeginStoryboard et une propriété MultiTrigger Non Oui Oui Oui Exemple de classe MultiTrigger
BeginStoryboard et un DataTrigger Non Oui Oui Oui Guide pratique pour déclencher une animation lorsque les données changent
BeginStoryboard et un MultiDataTrigger Non Oui Oui Oui Exemple de classe MultiDataTrigger
méthode Begin Oui Non Non Non Animer une propriété à l’aide d’un storyboard

L’exemple suivant utilise un Storyboard pour animer le Width d'un élément Rectangle et le Color d'un SolidColorBrush utilisé pour peindre cet 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 propriétés jointes TargetName et les propriétés jointes TargetProperty.

Ciblage des éléments constitutifs du framework, des éléments de contenu du framework et des objets gelables

La section précédente a mentionné que, pour qu’une animation trouve sa cible, elle doit connaître le nom de la cible et la propriété à animer. Il est simple de spécifier la propriété à animer : il suffit de définir TargetProperty avec le nom de la propriété à animer. Vous spécifiez le nom de l'objet dont la propriété que vous souhaitez animer en définissant la propriété Storyboard.TargetName dans l'animation.

Avertissement

Bien que vous puissiez utiliser la propriété Target pour établir une liaison directe à un objet en guise d’alternative à TargetName, elle 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, toutes les fenêtres, panneaux et contrôles 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 a une propriété Name. Si c’est le cas, il s’agit probablement d’un élément de framework ou d’un élément de contenu d’infrastructure. Pour être sûr, vérifiez la section 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’il a un nom, 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));

Les types Freezable sont les classes qui héritent de la classe Freezable. Exemples de Freezable, SolidColorBrush, RotateTransform et 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 scopes de noms WPF, consultez WPF XAML Namescopes. 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 il peut être ciblé indirectement. Les sections suivantes décrivent comment utiliser le ciblage indirect.

Ciblage indirect

Il est parfois impossible de cibler directement Freezable par une animation, par exemple lorsque Freezable est déclaré en tant que ressource ou utilisé pour définir une 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 l'animation TargetProperty avec une chaîne de propriétés qui commence par la propriété de l'élément framework ou de l'élément de contenu framework utilisé Freezable pour la définir et se termine par la propriété Freezable à 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 est figé, un clone sera créé et 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 la vue d’ensemble des objets freezables.

Notez également que, lors de l’utilisation du ciblage de propriété indirecte, il est possible de cibler des objets qui n’existent pas. Par exemple, vous pourriez supposer que la propriété Background d'un bouton particulier a été configurée avec un SolidColorBrush et essayer d'animer sa Couleur, alors qu'en réalité un LinearGradientBrush a été utilisé pour définir le Fond du bouton. Dans ces cas, aucune exception n’est levée ; l’animation n’a pas d’effet visible, car LinearGradientBrush ne réagit pas aux modifications de la propriété Color.

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

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

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

Syntaxe de propriété
ElementPropertyName.FreezablePropertyName

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

  • FreezablePropertyName est la propriété de Freezable à animer.

Le code suivant montre comment animer le Color d'un SolidColorBrush utilisé pour définir le Fill d'un 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>

Parfois, vous devez cibler un freezable contenu dans une collection ou un tableau.

Pour cibler un 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 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 PathParameters, vous devez créer un tableau de type DependencyProperty qui inclut une liste de champs identifiant les propriétés de dépendance. Le premier champ d’identificateur est destiné à la propriété du FrameworkElement ou du FrameworkContentElement que le Freezable est utilisé pour configurer. Le champ d’identificateur suivant représente la propriété de Freezable à cibler. Considérez-le comme une chaîne de propriétés qui connecte le Freezable à l'objet FrameworkElement.

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

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

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

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

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

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

L’exemple suivant montre le Path qui accompagnerait le 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 des exemples précédents pour animer le Color d'un SolidColorBrush, utilisé pour définir le Fill d'un élément 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);

Parfois, vous devez cibler un 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 pour animer le Angle d’un 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 freezable comme point de départ

Les sections précédentes ont décrit comment cibler indirectement un Freezable en commençant par un FrameworkElement ou un FrameworkContentElement et en créant une chaîne de propriétés menant à une sous-propriété Freezable. 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’un storyboard 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 la 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 de manière interactive le storyboard une fois qu’il a démarré. Voici une liste d’actions de storyboard contrôlables que vous utilisez avec des déclencheurs d’événements pour contrôler un storyboard.

Dans l’exemple suivant, les actions de storyboard contrôlables sont utilisées pour contrôler de manière interactive un storyboard.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="Microsoft.SDK.Animation.ControllableStoryboardExample"
  WindowTitle="Fading Rectangle Example">
  <StackPanel Margin="10">

    <Rectangle
      Name="MyRectangle"
      Width="100" 
      Height="100"
      Fill="Blue">
    </Rectangle>

    <Button Name="BeginButton">Begin</Button>
    <Button Name="PauseButton">Pause</Button>
    <Button Name="ResumeButton">Resume</Button>
    <Button Name="SkipToFillButton">Skip To Fill</Button>
    <Button Name="StopButton">Stop</Button>

    <StackPanel.Triggers>
      <EventTrigger RoutedEvent="Button.Click" SourceName="BeginButton">
        <BeginStoryboard Name="MyBeginStoryboard">
          <Storyboard>
            <DoubleAnimation
              Storyboard.TargetName="MyRectangle" 
              Storyboard.TargetProperty="(Rectangle.Opacity)"
              From="1.0" To="0.0" Duration="0:0:5" />
          </Storyboard>
        </BeginStoryboard>
      </EventTrigger>
      <EventTrigger RoutedEvent="Button.Click" SourceName="PauseButton">
        <PauseStoryboard BeginStoryboardName="MyBeginStoryboard" />
      </EventTrigger>
      <EventTrigger RoutedEvent="Button.Click" SourceName="ResumeButton">
        <ResumeStoryboard BeginStoryboardName="MyBeginStoryboard" />
      </EventTrigger>
      <EventTrigger RoutedEvent="Button.Click" SourceName="SkipToFillButton">
        <SkipStoryboardToFill BeginStoryboardName="MyBeginStoryboard" />
      </EventTrigger>
      <EventTrigger RoutedEvent="Button.Click" SourceName="StopButton">
        <StopStoryboard BeginStoryboardName="MyBeginStoryboard" />
      </EventTrigger>
    </StackPanel.Triggers>
  </StackPanel>
</Page>

Contrôle interactif d’un storyboard à l’aide de 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 produiront lors du prochain cycle 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 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 ni d’expressions de liaison de données pour définir les valeurs de propriété de Storyboard ou d'animation. C’est parce que tout à l’intérieur d’un Style doit être sûr pour les threads, et le système de minutage doit FreezeStoryboard les objets pour les rendre sûrs pour les threads. Un Storyboard ne peut être figé si lui 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 style, consultez l’exemple Animer dans un style .

Animer dans un 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 ne peut faire référence qu'aux objets enfants du ControlTemplate. Si TargetName n'est pas spécifié, l'animation cible l'élément sur lequel ControlTemplate est appliqué.

  • 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 ni d’expressions de liaison de données pour définir les valeurs de propriété de Storyboard ou d'animation. C’est parce que tout à l’intérieur d’un ControlTemplate doit être sûr pour les threads, et le système de minutage doit FreezeStoryboard les objets pour les rendre sûrs pour les threads. Un Storyboard ne peut être figé si lui 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 lorsque la valeur d'une propriété change

Dans les styles et les modèles de contrôle, vous pouvez utiliser des objets déclencheur pour démarrer un storyboard lorsqu'une propriété change. Pour obtenir des exemples, consultez Déclencher une animation lorsqu’une valeur de propriété change et s’anime dans un ControlTemplate.

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

Voir aussi