Cenni preliminari sugli storyboard
In questo argomento viene illustrato come usare Storyboard gli oggetti per organizzare e applicare animazioni. Descrive come modificare Storyboard in modo interattivo gli oggetti e descrive la sintassi di destinazione delle proprietà indirette.
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. È anche necessario sapere come usare le proprietà associate. Per altre informazioni sulle proprietà associate, vedere Cenni preliminari sulle proprietà associate.
Che cos'è uno storyboard
Le animazioni non sono l'unico tipo utile della sequenza temporale. Sono disponibili altre classi di sequenze temporali per organizzare set di sequenze temporali e per applicare le sequenze temporali alle proprietà. Le sequenze temporali dei TimelineGroup contenitori derivano dalla classe e includono ParallelTimeline e Storyboard.
Un Storyboard è un tipo di sequenza temporale del contenitore che fornisce informazioni di destinazione per le sequenze temporali contenute. Uno Storyboard può contenere qualsiasi tipo di Timeline, incluse altre sequenze temporali e animazioni del contenitore. Storyboard Gli oggetti consentono di combinare sequenze temporali che influiscono su un'ampia gamma di oggetti e proprietà in un singolo albero della sequenza temporale, semplificando l'organizzazione e il controllo di comportamenti di intervallo complessi. Si supponga, ad esempio, di volere un pulsante che esegua queste tre operazioni.
Aumentare le dimensioni e cambiare colore quando l'utente seleziona il pulsante.
Ridursi e tornare nuovamente alle dimensioni originali quando si fa clic su di esso.
Comprimersi e perdere il 50% di opacità quando viene disabilitato.
In questo caso, si dispone di più set di animazioni che vengono applicati allo stesso oggetto e si desiderano riprodurre in momenti diversi, a seconda dello stato del pulsante. Storyboard gli oggetti consentono di organizzare le animazioni e applicarle in gruppi a uno o più oggetti.
Dove è possibile usare uno storyboard
Un Storyboard oggetto può essere usato per animare le proprietà di dipendenza delle classi animabili . Per altre informazioni su ciò che rende animabile una classe, vedere Cenni preliminari sull'animazione. Tuttavia, poiché lo storyboard è una funzionalità a livello di framework, l'oggetto deve appartenere a NameScope di un FrameworkElement oggetto o .FrameworkContentElement
Ad esempio, è possibile usare un Storyboard oggetto per eseguire le operazioni seguenti:
Animare un SolidColorBrush elemento (elemento non framework) che disegna lo sfondo di un pulsante (un tipo di FrameworkElement),
Animare un SolidColorBrush elemento (elemento non framework) che disegna il riempimento di un GeometryDrawing elemento (elemento non framework) visualizzato usando (FrameworkElementImage).
Nel codice animare un SolidColorBrush oggetto dichiarato da una classe che contiene anche un FrameworkElementoggetto , se il SolidColorBrush relativo nome è stato registrato con tale FrameworkElementoggetto .
Non è tuttavia possibile utilizzare un Storyboard oggetto per animare un SolidColorBrush oggetto che non ha registrato il nome con un FrameworkElement oggetto o FrameworkContentElementoppure non è stato utilizzato per impostare una proprietà di o FrameworkElement FrameworkContentElement.
Come applicare animazioni con uno storyboard
Per usare un Storyboard oggetto per organizzare e applicare animazioni, aggiungere le animazioni come sequenze temporali figlio di Storyboard. La Storyboard classe fornisce le Storyboard.TargetName proprietà associate e Storyboard.TargetProperty . Impostare queste proprietà su un'animazione per specificare l'oggetto di destinazione e la proprietà relativi.
Per applicare animazioni alle relative destinazioni, iniziare Storyboard a usare un'azione trigger o un metodo. In XAML si usa un BeginStoryboard oggetto con un EventTriggeroggetto , Triggero DataTrigger. Nel codice è anche possibile usare il Begin metodo .
La tabella seguente illustra le diverse posizioni in cui ogni Storyboard tecnica di inizio è supportata: per istanza, stile, modello di controllo e modello di dati. "Per istanza" si riferisce alla tecnica di applicazione di 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 usando… | Per istanza | Style | Modello del controllo | Modello di dati | Esempio |
---|---|---|---|---|---|
BeginStoryboard e un EventTrigger | Sì | Sì | Sì | Sì | Animare una proprietà utilizzando uno storyboard |
BeginStoryboard e una proprietà Trigger | No | Sì | Sì | Sì | Attivare un'animazione quando il valore di una proprietà viene modificato |
BeginStoryboard e una proprietà MultiTrigger | No | Sì | Sì | Sì | Esempio di classe MultiTrigger |
BeginStoryboard e un DataTrigger | No | Sì | Sì | Sì | Procedura: Attivare un'animazione quando i dati vengono modificati |
BeginStoryboard e un MultiDataTrigger | No | Sì | Sì | Sì | Esempio di classe MultiDataTrigger |
Metodo Begin | Sì | No | No | No | Animare una proprietà utilizzando uno storyboard |
Nell'esempio seguente viene utilizzato un Storyboard oggetto per animare l'oggetto Width di un Rectangle elemento e Color di un SolidColorBrush oggetto utilizzato per disegnare tale Rectangleoggetto .
<!-- 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;
}
}
}
Le sezioni seguenti descrivono le TargetName proprietà associate e TargetProperty in modo più dettagliato.
Elementi del framework, elementi di contenuto del framework e oggetti Freezable
Nella sezione precedente è stato indicato che per trovare la relativa destinazione un'animazione deve conoscere il nome e la proprietà relativi cui aggiungere un'animazione. Specificare la proprietà da animare è semplice: è sufficiente impostare TargetProperty
con il nome della proprietà per animare. Specificare il nome dell'oggetto la cui proprietà si desidera animare impostando la Storyboard.TargetName proprietà sull'animazione.
Attenzione
Sebbene sia possibile usare la proprietà per eseguire l'associazione Target
diretta a un oggetto come alternativa a TargetName
, non è serializzabile. Non è garantito che l'oggetto Target
possa fare riferimento correttamente in XAML.
Affinché la TargetName proprietà funzioni, l'oggetto di destinazione deve avere un nome. L'assegnazione di un nome a un FrameworkElement oggetto o in FrameworkContentElement XAML è diversa dall'assegnazione di un nome a un Freezable oggetto .
Gli elementi del framework sono le classi che ereditano dalla FrameworkElement classe . Esempi di elementi del framework includono Window, DockPanelButton, e Rectangle. Praticamente tutte le finestre, i pannelli e i controlli sono elementi. Gli elementi del contenuto del framework sono le classi che ereditano dalla FrameworkContentElement classe . Esempi di elementi del contenuto del framework includono FlowDocument e Paragraph. Se non si sa se un tipo è un elemento del framework o un elemento di contenuto del framework, verificare la presenza di una proprietà Name. Se è presente, è probabile che sia un elemento del framework o un elemento di contenuto del framework. Per esserne certi, verificare la sezione Gerarchia di ereditarietà della relativa pagina di tipo.
Per abilitare la destinazione di un elemento framework o di un elemento del contenuto del framework in XAML, impostarne la Name proprietà. Nel codice è anche necessario usare il RegisterName metodo per registrare il nome dell'elemento con l'elemento per cui è stato creato un oggetto NameScope.
Nell'esempio seguente, tratto dall'esempio precedente, viene assegnato il nome MyRectangle
a Rectangle, un tipo di 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);
Dopo aver impostato un nome, è possibile aggiungere un'animazione a una proprietà di quell'elemento.
<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 i tipi sono le classi che ereditano dalla Freezable classe . Esempi di Freezable includono SolidColorBrush, RotateTransforme GradientStop.
Per abilitare la destinazione di un oggetto Freezable da un'animazione in XAML, usa la direttiva x:Name per assegnargli un nome. Nel codice si usa il metodo per registrarne il RegisterName nome con l'elemento per cui è stato creato un oggetto NameScope.
Nell'esempio seguente viene assegnato un nome a un Freezable oggetto .
<SolidColorBrush x:Name="MySolidColorBrush" Color="Blue" />
SolidColorBrush mySolidColorBrush = new SolidColorBrush(Colors.Blue);
this.RegisterName("MySolidColorBrush", mySolidColorBrush);
L'oggetto può essere quindi impostato come destinazione da 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 gli oggetti usano ambiti dei nomi per risolvere la TargetName proprietà. Per altre informazioni sugli ambiti dei nomi WPF, vedere NameScope XAML WPF. Se la TargetName proprietà viene omessa, l'animazione ha come destinazione l'elemento su cui è definito o, nel caso degli stili, l'elemento con stile.
In alcuni casi non è possibile assegnare un nome a un Freezable oggetto . Ad esempio, se un oggetto Freezable viene dichiarato come risorsa o usato per impostare un valore di proprietà in uno stile, non può essere assegnato un nome. Poiché non dispone di un nome, non è possibile impostarlo direttamente come destinazione, ma può essere impostato indirettamente. Le sezioni seguenti descrivono come usare l'impostazione indiretta delle destinazioni.
Impostazione indiretta delle destinazioni
In alcuni casi un Freezable oggetto non può essere indirizzato direttamente da un'animazione, ad esempio quando l'oggetto Freezable viene dichiarato come risorsa o usato per impostare un valore di proprietà in uno stile. In questi casi, anche se non è possibile indirizzarlo direttamente, è comunque possibile animare l'oggetto Freezable . Anziché impostare la TargetName proprietà con il nome di Freezable, si assegna il nome dell'elemento a cui appartiene l'elemento Freezable . Ad esempio, un SolidColorBrush oggetto utilizzato per impostare l'oggetto Fill di un elemento rettangolo appartiene a tale rettangolo. Per animare il pennello, impostare l'animazione TargetProperty con una catena di proprietà che inizia dalla proprietà dell'elemento del framework o dell'elemento Freezable di contenuto del framework utilizzata per impostare e terminare con la Freezable proprietà da animare.
<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);
Si noti che, se l'oggetto Freezable è bloccato, verrà creato un clone e tale clone verrà animato. In questo caso, la proprietà dell'oggetto HasAnimatedProperties originale continua a restituire false
, perché l'oggetto originale non è effettivamente animato. Per altre informazioni sulla duplicazione, vedere Cenni preliminari sugli oggetti Freezable.
Si noti inoltre che, quando si usa l'impostazione indiretta delle destinazioni di proprietà, è possibile impostare come destinazione oggetti che non esistono. Ad esempio, si potrebbe presupporre che l'oggetto Background di un determinato pulsante sia stato impostato con un SolidColorBrush oggetto e provare ad animare il colore, quando in realtà è stato usato un LinearGradientBrush oggetto per impostare lo sfondo del pulsante. In questi casi non viene generata alcuna eccezione; l'animazione non riesce ad avere un effetto visibile perché LinearGradientBrush non reagisce alle modifiche apportate alla Color proprietà.
Le sezioni seguenti descrivono la sintassi dell'impostazione indiretta delle destinazioni di proprietà in modo più dettagliato.
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, usare la sintassi seguente.
Sintassi delle proprietà |
---|
ElementPropertyName . FreezablePropertyName |
Dove
ElementPropertyName è la proprietà dell'oggetto FrameworkElement Freezable utilizzato per impostare e
FreezablePropertyName è la proprietà dell'oggetto Freezable da animare.
Nel codice seguente viene illustrato come animare l'oggetto Color di un SolidColorBrush oggetto utilizzato per impostare l'oggetto 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 una raccolta o una matrice.
Per impostare come destinazione un oggetto freezable contenuto in una raccolta, usare la sintassi del tracciato seguente.
Sintassi di path |
---|
ElementPropertyName .Children[ CollectionIndex ]. FreezablePropertyName |
Dove CollectionIndex è l'indice dell'oggetto nella relativa matrice o raccolta.
Si supponga, ad esempio, che un rettangolo abbia una TransformGroup risorsa applicata alla relativa RenderTransform proprietà e che si voglia animare una delle trasformazioni contenute.
<TransformGroup x:Key="MyTransformGroupResource"
x:Shared="False">
<ScaleTransform />
<RotateTransform />
</TransformGroup>
Nel codice seguente viene illustrato come animare la Angle proprietà dell'oggetto RotateTransform illustrato nell'esempio precedente.
<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 si crea un PropertyPath oggetto . Quando si crea , PropertyPathsi specifica un Path e PathParameters.
Per creare PathParameters, creare una matrice di tipo DependencyProperty contenente un elenco di campi identificatore di proprietà di dipendenza. Il primo campo dell'identificatore è relativo alla proprietà dell'oggetto FrameworkElement o FrameworkContentElement che Freezable viene utilizzato per impostare. Il campo identificatore successivo rappresenta la proprietà dell'oggetto Freezable di destinazione. Si consideri una catena di proprietà che connette l'oggetto Freezable all'oggetto FrameworkElement .
Di seguito è riportato un esempio di una catena di proprietà di dipendenza destinata all'oggetto Color di un SolidColorBrush oggetto utilizzato per impostare l'oggetto Fill di un elemento rettangolo.
DependencyProperty[] propertyChain =
new DependencyProperty[]
{Rectangle.FillProperty, SolidColorBrush.ColorProperty};
È anche necessario specificare un oggetto Path. È Path un oggetto String che indica Path come interpretare il relativo PathParametersoggetto . Usa la sintassi seguente.
Sintassi del percorso delle proprietà |
---|
( OwnerPropertyArrayIndex ).( FreezablePropertyArrayIndex ) |
Dove
OwnerPropertyArrayIndex è l'indice della DependencyProperty matrice che contiene l'identificatore della FrameworkElement proprietà Freezable dell'oggetto utilizzata per impostare e
FreezablePropertyArrayIndex è l'indice della DependencyProperty matrice che contiene l'identificatore della proprietà di destinazione.
Nell'esempio seguente viene illustrato l'oggetto Path che accompagna l'oggetto PathParameters definito nell'esempio precedente.
DependencyProperty[] propertyChain =
new DependencyProperty[]
{Rectangle.FillProperty, SolidColorBrush.ColorProperty};
string thePath = "(0).(1)";
Nell'esempio seguente viene combinato il codice negli esempi precedenti per animare l'oggetto Color di un SolidColorBrush oggetto utilizzato per impostare l'oggetto Fill di un elemento rettangolo.
// 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 una raccolta o una matrice. Si supponga, ad esempio, che un rettangolo abbia una TransformGroup risorsa applicata alla relativa RenderTransform proprietà e che si voglia animare una delle trasformazioni contenute.
<TransformGroup x:Key="MyTransformGroupResource"
x:Shared="False">
<ScaleTransform />
<RotateTransform />
</TransformGroup>
Per specificare come destinazione un Freezable oggetto contenuto in una raccolta, usare la sintassi del percorso seguente.
Sintassi di path |
---|
( OwnerPropertyArrayIndex ).( CollectionChildrenPropertyArrayIndex ) [ CollectionIndex ].( FreezablePropertyArrayIndex ) |
Dove CollectionIndex è l'indice dell'oggetto nella relativa matrice o raccolta.
Per impostare come destinazione la proprietà di , la seconda trasformazione in , si userà quanto segue e .To target the Angle property of the RotateTransform, the second transform in the TransformGroup, you would use the following Path and 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);
Nell'esempio seguente viene illustrato il codice completo per animare l'oggetto Angle di un RotateTransform oggetto contenuto all'interno di un oggetto 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);
Impostazione indiretta della destinazione con un oggetto Freezable come punto di partenza
Nelle sezioni precedenti è stato descritto come specificare indirettamente come destinazione un oggetto Freezable partendo da un FrameworkElement oggetto o FrameworkContentElement e creando una catena di proprietà a una Freezable sottoproprietà. È anche possibile usare come Freezable punto di partenza e indirettamente una delle relative Freezable sottoproprietà. Una restrizione aggiuntiva si applica quando si usa un Freezable oggetto come punto iniziale per la destinazione indiretta: l'avvio Freezable e ogni Freezable elemento e la sottoproprietà di destinazione indiretta non devono essere bloccati.
Controllo interattivo di uno storyboard in XAML
Per avviare uno storyboard in Extensible Application Markup Language (XAML), usa un'azione BeginStoryboard trigger. BeginStoryboard distribuisce le animazioni agli oggetti e alle proprietà che animano e avvia lo storyboard. Per informazioni dettagliate su questo processo, vedere Cenni preliminari sul sistema di animazione e temporizzazione. Se si assegna un BeginStoryboard nome specificando la relativa Name proprietà, è possibile impostarlo come storyboard controllabile. È quindi possibile controllare in modo interattivo lo storyboard dopo l'avvio. Di seguito è riportato un elenco di azioni dello storyboard controllabili da usare con i 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: arresta lo storyboard.
RemoveStoryboard: rimuove lo storyboard.
Nell'esempio seguente le azioni di storyboard controllabili vengono usate per controllare uno storyboard in modo interattivo.
<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>
Controllo interattivo di uno storyboard tramite il codice
Gli esempi precedenti hanno illustrato come aggiungere animazioni tramite le azioni trigger. Nel codice è anche possibile controllare uno storyboard usando metodi interattivi della Storyboard classe . Affinché un elemento Storyboard venga reso interattivo nel codice, è necessario usare l'overload appropriato del metodo dello Begin storyboard e specificarlo true
per renderlo controllabile. Per altre informazioni, vedere la Begin(FrameworkElement, Boolean) pagina.
L'elenco seguente mostra i metodi che possono essere usati per modificare un oggetto Storyboard dopo l'avvio:
Il vantaggio di usare questi metodi è che non è necessario creare Trigger o TriggerAction oggetti. È sufficiente un riferimento al controllabile Storyboard che si vuole modificare.
Nota
Tutte le azioni interattive eseguite su un Clocke quindi anche su un Storyboard si verificheranno sul segno di spunta successivo del motore di temporizzazione che si verificherà poco prima del rendering successivo. Ad esempio, se si usa il Seek metodo per passare a un altro punto di un'animazione, il valore della proprietà non cambia immediatamente, invece, il valore cambia al segno di spunta successivo del motore di temporizzazione.
Nell'esempio seguente viene illustrato come applicare e controllare le animazioni usando i metodi interattivi della 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
Aggiungere un'animazione in uno stile
È possibile usare Storyboard gli oggetti per definire le animazioni in un oggetto Style. L'animazione con un Storyboard oggetto in è Style simile all'uso di un'altra Storyboard posizione, con le tre eccezioni seguenti:
Non si specifica un oggetto TargetName. l'oggetto Storyboard è sempre destinato all'elemento a cui viene applicato l'oggetto Style . Per impostare come destinazione Freezable gli oggetti, è necessario usare la destinazione indiretta. Per altre informazioni sull'impostazione indiretta delle destinazioni, vedere la sezione Impostazione indiretta delle destinazioni.
Non è possibile specificare un oggetto SourceName per un oggetto EventTrigger o .Trigger
Non è possibile usare riferimenti a risorse dinamiche o espressioni di data binding per impostare o impostare Storyboard i valori delle proprietà di animazione. Questo perché tutto all'interno di deve Style essere thread-safe e il sistema di temporizzazione deve FreezeStoryboard oggetti per renderli thread-safe. Un Storyboard oggetto non può essere bloccato se le sequenze temporali figlio contengono riferimenti a risorse dinamiche o espressioni di data binding. Per altre informazioni sul blocco e altre Freezable funzionalità, vedere Cenni preliminari sugli oggetti Freezable.
In XAML non è possibile dichiarare gestori eventi per Storyboard gli eventi di animazione o .
Per un esempio che mostra come definire uno storyboard in uno stile, vedere l'esempio Aggiungere un'animazione in uno stile.
Eseguire un'animazione in un ControlTemplate
È possibile usare Storyboard gli oggetti per definire le animazioni in un oggetto ControlTemplate. L'animazione con un Storyboard oggetto in è ControlTemplate simile all'uso di un'altra Storyboard posizione, con le due eccezioni seguenti:
può TargetName fare riferimento solo agli oggetti figlio dell'oggetto ControlTemplate. Se TargetName non viene specificato, l'animazione è destinata all'elemento a cui viene applicato l'oggetto ControlTemplate .
L'oggetto SourceName per un oggetto EventTrigger o può Trigger fare riferimento solo agli oggetti figlio dell'oggetto ControlTemplate.
Non è possibile usare riferimenti a risorse dinamiche o espressioni di data binding per impostare o impostare Storyboard i valori delle proprietà di animazione. Questo perché tutto all'interno di deve ControlTemplate essere thread-safe e il sistema di temporizzazione deve FreezeStoryboard oggetti per renderli thread-safe. Un Storyboard oggetto non può essere bloccato se le sequenze temporali figlio contengono riferimenti a risorse dinamiche o espressioni di data binding. Per altre informazioni sul blocco e altre Freezable funzionalità, vedere Cenni preliminari sugli oggetti Freezable.
In XAML non è possibile dichiarare gestori eventi per Storyboard gli eventi di animazione o .
Per un esempio che mostra come definire uno storyboard in un ControlTemplateoggetto , vedere l'esempio Animate in a ControlTemplate .
Aggiungere un'animazione quando viene modificato il valore di una proprietà
Negli stili e nei modelli di controllo è possibile usare oggetti Trigger per avviare uno storyboard quando una proprietà viene modificata. Per esempi, vedere Attivare un'animazione quando il valore di una proprietà viene modificato ed Eseguire un'animazione in un oggetto ControlTemplate.
Le animazioni applicate dagli oggetti proprietà Trigger si comportano in modo più complesso rispetto EventTrigger alle animazioni o alle animazioni avviate usando Storyboard metodi. Essi "handoff" con animazioni definite da altri Trigger oggetti, ma compongono con EventTrigger e animazioni attivate dal metodo.
Vedi anche
.NET Desktop feedback