Cenni preliminari sugli storyboard
In questo argomento viene illustrato come utilizzare gli oggetti Storyboard per organizzare e applicare animazioni. Viene illustrato come modificare in modo interattivo gli oggetti Storyboard e come utilizzare la sintassi indiretta relativa alle proprietà.
Prerequisiti
Per comprendere questo argomento, è necessario conoscere i diversi tipi di animazione e le relative funzionalità di base. Per un'introduzione alle animazioni, vedere Cenni preliminari sull'animazione. È inoltre consigliabile conoscere le modalità di utilizzo delle proprietà collegate. Per ulteriori informazioni sulle proprietà collegate, vedere Cenni preliminari sulle proprietà associate.
Definizione di storyboard
Le animazioni non sono l'unico tipo utile di sequenza temporale. Vengono fornite altre classi di sequenze temporali per organizzare insiemi di sequenze e per applicare sequenze alle proprietà. Le sequenze temporali contenitore derivano dalla classe TimelineGroup e includono ParallelTimeline e Storyboard.
Uno Storyboard è un tipo di sequenza temporale contenitore che fornisce informazioni per le sequenze in essa contenute. Uno storyboard può contenere qualsiasi tipo di Timeline, incluse altre animazioni e altre sequenze temporali contenitore. Gli oggetti Storyboard consentono di combinare sequenze temporali che influiscono su numerosi oggetti e proprietà in una singola struttura ad albero di sequenze, semplificando l'organizzazione e il controllo di comportamenti di temporizzazione complessi. Si supponga, ad esempio, di voler disporre di un pulsante avente le tre caratteristiche riportate di seguito.
Aumentare di volume e cambiare colore quando viene selezionato.
Ridursi e tornare nuovamente alle dimensioni originali quando viene fatto clic su di esso.
Comprimersi e perdere il 50% di opacità quando viene disabilitato.
In questo caso, si dispone di più set di animazioni applicabili allo stesso oggetto e si desidera eseguirli in momenti diversi, a seconda dello stato del pulsante. Gli oggetti Storyboard consentono di organizzare le animazioni e di applicarle in gruppi a uno o più oggetti.
Dove utilizzare uno storyboard
Un oggetto Storyboard può essere utilizzato per animare le proprietà di dipendenza di classi che supportano l'animazione. Per ulteriori informazioni sul supporto delle classi per le animazioni, vedere Cenni preliminari sull'animazione). Poiché lo storyboard è una funzionalità a livello di framework, l'oggetto deve appartenere all'oggetto NameScope di FrameworkElement o di FrameworkContentElement.
È ad esempio possibile utilizzare uno Storyboard per eseguire le operazioni riportate di seguito:
Animare un oggetto SolidColorBrush (elemento non framework) che consente di disegnare lo sfondo di un pulsante (un tipo di FrameworkElement)
Animare un oggetto SolidColorBrush (elemento non framework) che consente di disegnare il riempimento di un oggetto GeometryDrawing (elemento non framework) visualizzato tramite un oggetto Image (FrameworkElement).
Nel codice, animare un oggetto SolidColorBrush dichiarato da una classe che contiene anche un oggetto FrameworkElement, se l'oggetto SolidColorBrush ha registrato il relativo nome con FrameworkElement.
Non è tuttavia possibile utilizzare uno Storyboard per animare un oggetto SolidColorBrush che non ha registrato il proprio nome con FrameworkElement o FrameworkContentElement oppure che non è stato utilizzato per impostare una proprietà di un oggetto FrameworkElement o FrameworkContentElement.
Come applicare animazioni con uno storyboard
Per utilizzare uno Storyboard per organizzare e applicare animazioni, è necessario aggiungere le animazioni come sequenze temporali figlio dello Storyboard. La classe Storyboard fornisce le proprietà collegate Storyboard.TargetName e Storyboard.TargetProperty. Queste proprietà devono essere impostate su un'animazione per specificare la proprietà e l'oggetto di destinazione relativi.
Per applicare animazioni alle relative destinazioni, dare inizio allo Storyboard utilizzando un'azione trigger o un metodo. In XAML, utilizzare un oggetto BeginStoryboard con EventTrigger, Trigger o DataTrigger. Nel codice, è anche possibile utilizzare il metodo Begin.
Nella tabella riportata di seguito sono riportate le diverse posizioni in cui è supportata la tecnica di inizio di ciascuno Storyboard: per istanza, stile, modello di controllo e modello di dati. Per istanza" si riferisce alla tecnica di applicare un'animazione o uno storyboard direttamente a istanze di un oggetto, piuttosto che in uno stile, un modello di controllo o un modello di dati.
Storyboard iniziato utilizzando… |
Per istanza |
Stile |
Modello di controllo |
Modello di dati |
Esempio |
---|---|---|---|---|---|
Sì |
Sì |
Sì |
Sì |
||
BeginStoryboard e Trigger della proprietà |
No |
Sì |
Sì |
Sì |
Procedura: attivare un'animazione quando il valore di una proprietà viene modificato |
No |
Sì |
Sì |
Sì |
||
Metodo Begin |
Sì |
No |
No |
No |
Nell'esempio riportato di seguito viene utilizzato uno Storyboard per animare la proprietà Width di un elemento Rectangle e la proprietà Color di un oggetto SolidColorBrush utilizzato per disegnare quel Rectangle.
<!-- This example shows how to animate with a storyboard.-->
<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://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>
Imports System
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Data
Imports System.Windows.Shapes
Imports System.Windows.Input
Namespace Microsoft.Samples.Animation
Public Class StoryboardsExample
Inherits Page
Public Sub New()
Me.WindowTitle = "Storyboards Example"
Dim myStackPanel As New StackPanel()
myStackPanel.Margin = New Thickness(20)
Dim myRectangle As New Rectangle()
myRectangle.Name = "MyRectangle"
' Create a name scope for the page.
NameScope.SetNameScope(Me, New NameScope())
Me.RegisterName(myRectangle.Name, myRectangle)
myRectangle.Width = 100
myRectangle.Height = 100
Dim mySolidColorBrush As New SolidColorBrush(Colors.Blue)
Me.RegisterName("MySolidColorBrush", mySolidColorBrush)
myRectangle.Fill = mySolidColorBrush
Dim myDoubleAnimation As 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))
Dim myColorAnimation As 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))
Dim myStoryboard As New Storyboard()
myStoryboard.Children.Add(myDoubleAnimation)
myStoryboard.Children.Add(myColorAnimation)
AddHandler myRectangle.MouseEnter, Sub(sender As Object, e As MouseEventArgs) myStoryboard.Begin(Me)
myStackPanel.Children.Add(myRectangle)
Me.Content = myStackPanel
End Sub
End Class
End Namespace
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;
}
}
}
Nelle sezioni riportate di seguito vengono descritte più dettagliatamente le proprietà collegate TargetName e TargetProperty.
Elementi del framework, elementi di contenuto del framework e oggetti Freezable
Nella sezione precedente è stato specificato che per trovare la relativa destinazione un'animazione deve conoscere il nome e la proprietà da animare relativi. Per specificare la proprietà da animare,è sufficiente impostare la proprietà Storyboard.TargetProperty con il nome della proprietà da animare. Specificare il nome dell'oggetto di cui animare la proprietà impostando la proprietà Storyboard.TargetName sull'animazione.
Affinché la proprietà TargetName sia funzionante, l'oggetto di destinazione deve avere un nome. La procedura di assegnazione di un nome a un oggetto FrameworkElement o FrameworkContentElement in XAML non corrisponde a quella utilizzata per assegnare un nome a un oggetto Freezable.
Gli elementi del framework sono classi che ereditano dalla classe FrameworkElement. Elementi del framework di questo tipo sono rappresentati ad esempio da Window, DockPanel, Button e Rectangle. Praticamente tutte le finestre, i pannelli e i controlli sono elementi. Gli elementi di contenuto del framework sono classi che ereditano dalla classe FrameworkContentElement. Elementi di contenuto del framework di questo tipo sono rappresentati ad esempio da FlowDocument e Paragraph. Se non si è in grado di stabilire se un tipo è un elemento del framework o un elemento di contenuto del framework, verificare se dispone della proprietà Name. In caso affermativo, si tratta probabilmente di un elemento del framework o di un elemento di contenuto del framework. Per avere la certezza, controllare la sezioneGerarchia di ereditarietà della pagina relativa al tipo.
Per utilizzare come destinazione un elemento del framework o un elemento di contenuto del framework in XAML, impostare la relativa proprietà Name. Nel codice è inoltre necessario utilizzare il metodo RegisterName per registrare il nome dell'elemento con l'elemento per il quale è stato creato un oggetto NameScope.
Nell'esempio riportato di seguito, ricavato dall'esempio precedente, viene assegnato il nome MyRectangle a Rectangle, un tipo di FrameworkElement.
<Rectangle Name="MyRectangle"
Width="100"
Height="100">
Dim myRectangle As New Rectangle()
myRectangle.Name = "MyRectangle"
' Create a name scope for the page.
NameScope.SetNameScope(Me, New NameScope())
Me.RegisterName(myRectangle.Name, myRectangle)
Rectangle myRectangle = new Rectangle();
myRectangle.Name = "MyRectangle";
// Create a name scope for the page.
NameScope.SetNameScope(this, new NameScope());
this.RegisterName(myRectangle.Name, myRectangle);
Dopo l'assegnazione del nome all'elemento, è possibile animare una proprietà.
<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))
Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
Storyboard.SetTargetProperty(myDoubleAnimation,
new PropertyPath(Rectangle.WidthProperty));
I tipi Freezable sono classi che ereditano dalla classe Freezable. Esempi di oggetti Freezable includono SolidColorBrush, RotateTransform e GradientStop.
Per utilizzare come destinazione un oggetto Freezable tramite un'animazione in XAML, utilizzare Direttiva x:Name per assegnare ad esso un nome. Nel codice è necessario utilizzare il metodo RegisterName per registrare il suo nome con l'elemento per il quale è stato creato un oggetto NameScope.
Nell'esempio riportato di seguito viene assegnato un nome all'oggetto Freezable.
<SolidColorBrush x:Name="MySolidColorBrush" Color="Blue" />
Dim mySolidColorBrush As New SolidColorBrush(Colors.Blue)
Me.RegisterName("MySolidColorBrush", mySolidColorBrush)
SolidColorBrush mySolidColorBrush = new SolidColorBrush(Colors.Blue);
this.RegisterName("MySolidColorBrush", mySolidColorBrush);
L'oggetto può essere impostato come destinazione di un'animazione.
<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.SetTargetName(myColorAnimation, "MySolidColorBrush");
Storyboard.SetTargetProperty(myColorAnimation,
new PropertyPath(SolidColorBrush.ColorProperty));
Gli oggetti Storyboard utilizzano ambiti di nomi per risolvere la proprietà TargetName. Per ulteriori informazioni sugli ambiti di nomi WPF, vedere NameScope XAML WPF. Se si omette la proprietà TargetName, l'animazione considera come destinazione l'elemento su cui è stata definita o, nel caso di stili, l'elemento con stile.
Talvolta non è possibile assegnare un nome a un oggetto Freezable. Se, ad esempio, un oggetto Freezable viene dichiarato come una risorsa o utilizzato per impostare un valore di proprietà in uno stile, non è possibile assegnare ad esso un nome. Poiché non dispone di un nome, non può essere impostato direttamente come destinazione, ma solo indirettamente. Nelle sezioni riportate di seguito viene illustrato come impostare indirettamente le destinazioni.
Impostazione indiretta delle destinazioni
In alcuni casi, un oggetto Freezable non può essere impostato direttamente come destinazione da un'animazione, ad esempio quando l'oggetto Freezable viene dichiarato come una risorsa o utilizzato per impostare un valore di proprietà in uno stile. In questi casi, anche se non è possibile impostarlo direttamente come destinazione, è ancora possibile animare l'oggetto Freezable. Anziché impostare la proprietà TargetName con il nome dell'oggetto Freezable, assegnare ad esso il nome dell'elemento a cui "appartiene" l'oggetto Freezable. Ad esempio, un oggetto SolidColorBrush utilizzato per impostare la proprietà Fill di un elemento rettangolo appartiene a quel rettangolo. Per animare il pennello, impostare la proprietà TargetProperty dell'animazione con una catena di proprietà che inizia dalla proprietà dell'elemento del framework o dell'elemento di contenuto del framework impostato con l'oggetto Freezable e termina con la proprietà Freezable da animare.
<ColorAnimation
Storyboard.TargetName="Rectangle01"
Storyboard.TargetProperty="Fill.Color"
From="Blue" To="AliceBlue" Duration="0:0:1" />
Dim propertyChain() As DependencyProperty = {Rectangle.FillProperty, SolidColorBrush.ColorProperty}
Dim thePath As String = "(0).(1)"
Dim myPropertyPath As New PropertyPath(thePath, propertyChain)
Storyboard.SetTargetProperty(myColorAnimation, myPropertyPath)
DependencyProperty[] propertyChain =
new DependencyProperty[]
{Rectangle.FillProperty, SolidColorBrush.ColorProperty};
string thePath = "(0).(1)";
PropertyPath myPropertyPath = new PropertyPath(thePath, propertyChain);
Storyboard.SetTargetProperty(myColorAnimation, myPropertyPath);
Se l'oggetto Freezable è bloccato, viene creato un duplicato e tale duplicato verrà animato. In questo caso, la proprietà HasAnimatedProperties dell'oggetto originale continua a restituire false, perché l'oggetto originale non è effettivamente animato. Per ulteriori informazioni sulla duplicazione, vedere Cenni preliminari sugli oggetti Freezable.
Quando si impostano indirettamente le destinazioni delle proprietà, è possibile impostare come destinazioni oggetti che non esistono. Si supponga, ad esempio, che la proprietà Background di un pulsante sia stata impostata con un oggetto SolidColorBrush e si sia tentato di animare la relativa proprietà Color quando in realtà era stato utilizzato un oggetto LinearGradientBrush per impostare la proprietà Background del pulsante. In questi casi, non viene generata alcuna eccezione; l'animazione non avrà un effetto visibile perché LinearGradientBrush non reagisce alle modifiche apportate alla proprietà Color.
Nelle sezioni riportate di seguito viene illustrato in dettaglio come impostare in modo indiretto le destinazioni delle proprietà.
Impostazione indiretta della destinazione di una proprietà di un oggetto Freezable in XAML
Per impostare come destinazione una proprietà di un oggetto Freezable in XAML, utilizzare la sintassi riportata di seguito.
ElementPropertyName.FreezablePropertyName |
Percorso
ElementPropertyName è la proprietà dell'oggetto FrameworkElement impostato tramite l'oggetto Freezable e
FreezablePropertyName è la proprietà dell'oggetto Freezable da animare.
Nel codice riportato di seguito viene illustrato come animare la proprietà Color di un oggetto SolidColorBrush utilizzato per la proprietà
Fill di un elemento rettangolo.
<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>
Talvolta, è necessario impostare come destinazione un oggetto Freezable contenuto in un insieme o in una matrice.
Per impostare come destinazione un oggetto Freezable contenuto in un insieme, utilizzare la sintassi del percorso riportata di seguito.
ElementPropertyName.Children[CollectionIndex].FreezablePropertyName |
Dove CollectionIndex è l'indice dell'oggetto nella matrice o nell'insieme.
Si supponga, ad esempio, che alla proprietà RenderTransform di un rettangolo sia applicata una risorsa TransformGroup e di volere animare una delle trasformazioni in essa contenute.
<TransformGroup x:Key="MyTransformGroupResource"
x:Shared="False">
<ScaleTransform />
<RotateTransform />
</TransformGroup>
Nell'esempio di codice riportato di seguito viene illustrato come animare la proprietà Angle dell'oggetto RotateTransform illustrato nel precedente esempio.
<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>
Impostazione indiretta della destinazione di una proprietà di un oggetto Freezable nel codice
Nel codice creare un oggetto PropertyPath. Quando si crea l'oggetto PropertyPath, si specifica una proprietà Path e una proprietà PathParameters.
Per creare PathParameters, si crea una matrice di tipo DependencyProperty che contiene un elenco di campi dell'identificatore di proprietà di dipendenza. Il primo campo dell'identificatore è per la proprietà dell'oggetto FrameworkElement o FrameworkContentElement impostato tramite l'oggetto Freezable. Il campo dell'identificatore successivo rappresenta la proprietà dell'oggetto Freezable da impostare come destinazione. Considerarlo come una catena di proprietà che collega l'oggetto Freezable all'oggetto FrameworkElement.
Di seguito è riportato un esempio di una catena di proprietà di dipendenza che imposta come destinazione la proprietà Color di un oggetto SolidColorBrush utilizzato per impostare la proprietà Fill di un elemento rettangolo.
Dim propertyChain() As DependencyProperty = {Rectangle.FillProperty, SolidColorBrush.ColorProperty}
DependencyProperty[] propertyChain =
new DependencyProperty[]
{Rectangle.FillProperty, SolidColorBrush.ColorProperty};
È inoltre necessario specificare una proprietà Path. Path è un oggetto String che indica alla proprietà Path come interpretare la proprietà PathParameters. Viene utilizzata la seguente sintassi.
(OwnerPropertyArrayIndex).(FreezablePropertyArrayIndex) |
Percorso
OwnerPropertyArrayIndex è l'indice della matrice DependencyProperty che contiene l'identificatore della proprietà dell'oggetto FrameworkElement impostato tramite Freezable e
FreezablePropertyArrayIndex è l'indice della matrice DependencyProperty che contiene l'identificatore della proprietà da impostare come destinazione.
Nell'esempio riportato di seguito viene illustrata la proprietà Path associata alla proprietà PathParameters definita nel precedente esempio.
Dim propertyChain() As DependencyProperty = {Rectangle.FillProperty, SolidColorBrush.ColorProperty}
Dim thePath As String = "(0).(1)"
DependencyProperty[] propertyChain =
new DependencyProperty[]
{Rectangle.FillProperty, SolidColorBrush.ColorProperty};
string thePath = "(0).(1)";
Nell'esempio riportato di seguito viene combinato il codice degli esempi precedenti per animare la proprietà Color di un oggetto SolidColorBrush utilizzato per impostare la proprietà Fill di un elemento rettangolo.
' Create a name scope for the page.
NameScope.SetNameScope(Me, New NameScope())
Dim rectangle01 As New Rectangle()
rectangle01.Name = "Rectangle01"
Me.RegisterName(rectangle01.Name, rectangle01)
rectangle01.Width = 100
rectangle01.Height = 100
rectangle01.Fill = CType(Me.Resources("MySolidColorBrushResource"), SolidColorBrush)
Dim myColorAnimation As New ColorAnimation()
myColorAnimation.From = Colors.Blue
myColorAnimation.To = Colors.AliceBlue
myColorAnimation.Duration = New Duration(TimeSpan.FromSeconds(1))
Storyboard.SetTargetName(myColorAnimation, rectangle01.Name)
Dim propertyChain() As DependencyProperty = {Rectangle.FillProperty, SolidColorBrush.ColorProperty}
Dim thePath As String = "(0).(1)"
Dim myPropertyPath As New PropertyPath(thePath, propertyChain)
Storyboard.SetTargetProperty(myColorAnimation, myPropertyPath)
Dim myStoryboard As New Storyboard()
myStoryboard.Children.Add(myColorAnimation)
Dim myBeginStoryboard As New BeginStoryboard()
myBeginStoryboard.Storyboard = myStoryboard
Dim myMouseEnterTrigger As New EventTrigger()
myMouseEnterTrigger.RoutedEvent = Rectangle.MouseEnterEvent
myMouseEnterTrigger.Actions.Add(myBeginStoryboard)
rectangle01.Triggers.Add(myMouseEnterTrigger)
// 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);
Talvolta, è necessario impostare come destinazione un oggetto Freezable contenuto in un insieme o in una matrice. Si supponga, ad esempio, che alla proprietà RenderTransform di un rettangolo sia applicata una risorsa TransformGroup e di volere animare una delle trasformazioni in essa contenute.
<TransformGroup x:Key="MyTransformGroupResource"
x:Shared="False">
<ScaleTransform />
<RotateTransform />
</TransformGroup>
Per impostare come destinazione un oggetto Freezable contenuto in un insieme, utilizzare la sintassi del percorso riportata di seguito.
(OwnerPropertyArrayIndex).( CollectionChildrenPropertyArrayIndex) [CollectionIndex ].(FreezablePropertyArrayIndex) |
Dove CollectionIndex è l'indice dell'oggetto nella matrice o nell'insieme.
Per impostare come destinazione la proprietà Angle dell'oggetto RotateTransform, la seconda trasformazione in TransformGroup, utilizzare le proprietà Path e PathParameters.
Dim propertyChain() As DependencyProperty = { Rectangle.RenderTransformProperty, TransformGroup.ChildrenProperty, RotateTransform.AngleProperty }
Dim thePath As String = "(0).(1)[1].(2)"
Dim myPropertyPath As New PropertyPath(thePath, propertyChain)
Storyboard.SetTargetProperty(myDoubleAnimation, myPropertyPath)
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);
Nell'esempio riportato di seguito viene illustrato il codice completo per animare la proprietà Angle di un oggetto RotateTransform contenuto in un TransformGroup.
Dim rectangle02 As New Rectangle()
rectangle02.Name = "Rectangle02"
Me.RegisterName(rectangle02.Name, rectangle02)
rectangle02.Width = 100
rectangle02.Height = 100
rectangle02.Fill = Brushes.Blue
rectangle02.RenderTransform = CType(Me.Resources("MyTransformGroupResource"), TransformGroup)
Dim myDoubleAnimation As New DoubleAnimation()
myDoubleAnimation.From = 0
myDoubleAnimation.To = 360
myDoubleAnimation.Duration = New Duration(TimeSpan.FromSeconds(1))
Storyboard.SetTargetName(myDoubleAnimation, rectangle02.Name)
Dim propertyChain() As DependencyProperty = { Rectangle.RenderTransformProperty, TransformGroup.ChildrenProperty, RotateTransform.AngleProperty }
Dim thePath As String = "(0).(1)[1].(2)"
Dim myPropertyPath As New PropertyPath(thePath, propertyChain)
Storyboard.SetTargetProperty(myDoubleAnimation, myPropertyPath)
Dim myStoryboard As New Storyboard()
myStoryboard.Children.Add(myDoubleAnimation)
Dim myBeginStoryboard As New BeginStoryboard()
myBeginStoryboard.Storyboard = myStoryboard
Dim myMouseEnterTrigger As New EventTrigger()
myMouseEnterTrigger.RoutedEvent = Rectangle.MouseEnterEvent
myMouseEnterTrigger.Actions.Add(myBeginStoryboard)
rectangle02.Triggers.Add(myMouseEnterTrigger)
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);
Impostazione indiretta della destinazione con un oggetto Freezable come punto di partenza
Nelle sezioni precedenti veniva illustrato come impostare indirettamente come destinazione un oggetto Freezable partendo da un oggetto FrameworkElement o FrameworkContentElement e creando una catena di proprietà a una proprietà secondaria Freezable. È inoltre possibile utilizzare un oggetto Freezable come punto di partenza e impostare indirettamente come destinazione una delle proprietà secondarie dell'oggetto Freezable. È tuttavia necessario tenere conto di un'ulteriore limitazione quando si utilizza un oggetto Freezable come punto di partenza per l'impostazione indiretta delle destinazioni: l'oggetto Freezable iniziale e ogni oggetto Freezable presente tra esso e la proprietà secondaria impostata indirettamente come destinazione non deve essere bloccato.
Controllo interattivo di uno storyboard in XAML
Per avviare uno storyboard in Extensible Application Markup Language (XAML), utilizzare un'azione trigger BeginStoryboard. BeginStoryboard distribuisce le animazioni agli oggetti e alle proprietà che vengono animati, quindi avvia lo storyboard. Per informazioni dettagliate su questo processo, vedere Cenni preliminari sull'animazione e sul sistema di temporizzazione. Se si assegna un nome allo BeginStoryboard specificando la relativa proprietà Name, è possibile renderlo controllabile. È quindi possibile controllare in modo interattivo lo storyboard dopo il suo avvio. Di seguito è riportato un elenco di azioni dello storyboard controllabili che è possibile utilizzare con trigger di evento per controllare uno storyboard.
PauseStoryboard: sospende lo storyboard.
ResumeStoryboard: riprende uno storyboard sospeso.
SetStoryboardSpeedRatio: modifica la velocità dello storyboard.
SkipStoryboardToFill: sposta uno storyboard alla fine del periodo di riempimento, se presente.
StopStoryboard: interrompe lo storyboard.
RemoveStoryboard: rimuove lo storyboard.
Nell'esempio riportato di seguito vengono utilizzate azioni di storyboard controllabili per controllare in modo interattivo uno storyboard.
<Page
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://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>
Controllo interattivo di uno storyboard tramite il codice
Negli esempi precedenti veniva illustrato come eseguire animazioni utilizzando azioni trigger. Nel codice, è inoltre possibile controllare uno storyboard utilizzando metodi interattivi della classe Storyboard. Per rendere interattivo uno Storyboard nel codice, è necessario utilizzare l'overload appropriato del metodo Begin dello storyboard e specificare true per renderlo controllabile. Per ulteriori informazioni, vedere la pagina Begin(FrameworkElement, Boolean).
Di seguito sono elencati i metodi che è possibile utilizzare per modificare uno Storyboard dopo il suo avvio:
Il vantaggio derivante dall'utilizzo di questi metodi è che non è necessario creare oggetti Trigger o TriggerAction; è sufficiente disporre di un riferimento allo Storyboard controllabile che si desidera modificare.
Nota: tutte le azioni interattive eseguite in un oggetto Clock, e di conseguenza in uno Storyboard avranno luogo in corrispondenza del tick successivo del motore di temporizzazione che precederà di poco il rendering successivo. Ad esempio, se si utilizza il metodo Seek per passare a un altro punto di un'animazione, il valore della proprietà non cambia immediatamente, ma al tick successivo del motore di temporizzazione.
Nell'esempio riportato di seguito viene illustrato come applicare e controllare le animazioni utilizzando i metodi interattivi della classe Storyboard.
Imports Microsoft.VisualBasic
Imports System
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
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);
}
}
}
Animazione in uno stile
È possibile utilizzare gli oggetti Storyboard per definire animazioni in uno Style. L'esecuzione di animazioni con uno Storyboard in uno Style presenta delle analogie con l'utilizzo di uno Storyboard in altre situazioni, con le tre eccezioni seguenti:
Non si specifica una proprietà TargetName; lo Storyboard imposta sempre come destinazione l'elemento a cui viene applicato lo Style. Per impostare come destinazione gli oggetti Freezable, è necessario utilizzare la modalità indiretta. Per ulteriori informazioni sulla modalità indiretta, vedere la sezione Impostazione indiretta delle destinazioni.
Non è possibile specificare una proprietà SourceName per un oggetto EventTrigger o Trigger.
Non è possibile utilizzare espressioni di associazione dati o riferimenti di risorsa dinamici per impostare valori di proprietà di Storyboard o animazioni perché quanto contenuto in uno Style deve essere thread-safe e il sistema di temporizzazione deve utilizzare il metodo Freeze sugli oggetti Storyboard per renderli thread-safe. Non è possibile bloccare uno Storyboard se lo storyboard stesso e le relative sequenze temporali figlio contengono espressioni di associazione dati o riferimenti di risorsa dinamici. Per ulteriori informazioni sul blocco e su altre funzionalità Freezable, vedere Cenni preliminari sugli oggetti Freezable.
In XAML, non è possibile dichiarare gestori eventi per eventi animazione o Storyboard.
Per un esempio in cui viene illustrato come dichiarare uno storyboard in uno stile, vedere l'esempio Procedura: aggiungere un'animazione in uno stile.
Animazione in un ControlTemplate
È possibile utilizzare gli oggetti Storyboard per definire animazioni in un oggetto ControlTemplate. L'esecuzione di animazioni con uno Storyboard in un oggetto ControlTemplate presenta delle analogie con l'utilizzo di uno Storyboard in altre situazioni, con le due eccezioni seguenti:
La proprietà TargetName può unicamente fare riferimento agli oggetti figlio dell'oggetto ControlTemplate. La proprietà TargetName non è specificata, la destinazione dell'animazione è rappresentata dall'elemento a cui viene applicato l'oggetto ControlTemplate.
La proprietà SourceName di un oggetto EventTrigger o Trigger può unicamente fare riferimento agli oggetti figlio dell'oggetto ControlTemplate.
Non è possibile utilizzare espressioni di associazione dati o riferimenti di risorsa dinamici per impostare valori di proprietà di Storyboard o animazioni perché quanto contenuto in uno ControlTemplate deve essere thread-safe e il sistema di temporizzazione deve utilizzare il metodo Freeze sugli oggetti Storyboard per renderli thread-safe. Non è possibile bloccare uno Storyboard se lo storyboard stesso e le relative sequenze temporali figlio contengono espressioni di associazione dati o riferimenti di risorsa dinamici. Per ulteriori informazioni sul blocco e su altre funzionalità Freezable, vedere Cenni preliminari sugli oggetti Freezable.
In XAML, non è possibile dichiarare gestori eventi per eventi animazione o Storyboard.
Per un esempio in cui viene illustrato come definire uno storyboard in un oggetto ControlTemplate, vedere l'esempio Procedura: eseguire un'animazione in un oggetto ControlTemplate.
Esecuzione di un'animazione quando viene modificato il valore di una proprietà
Negli stili e nei modelli di controllo, è possibile utilizzare oggetti Trigger per avviare uno storyboard alla modifica di una proprietà. Per i relativi esempi, vedere Procedura: attivare un'animazione quando il valore di una proprietà viene modificato e Procedura: eseguire un'animazione in un oggetto ControlTemplate.
Le animazioni applicate tramite oggetti Trigger di proprietà dimostrano un comportamento più complesso rispetto alle animazioni EventTrigger o a quelle avviate tramite i metodi Storyboard. Vengono fornite con animazioni definite da altri oggetti Trigger, ma possono essere combinate con animazioni EventTrigger e con animazioni attivate tramite metodi.
Vedere anche
Concetti
Cenni preliminari sull'animazione
Cenni preliminari sulle tecniche di animazione delle proprietà