Overzicht van Storyboards
In dit onderwerp wordt beschreven hoe u Storyboard objecten kunt gebruiken om animaties te ordenen en toe te passen. Het beschrijft hoe u interactief Storyboard-objecten manipuleert en de indirecte eigenschapssyntaxis.
Voorwaarden
Als u dit onderwerp wilt begrijpen, moet u bekend zijn met de verschillende animatietypen en de bijbehorende basisfuncties. Zie het Animatieoverzichtvoor een inleiding tot animatie. U moet ook weten hoe u gekoppelde eigenschappen moet gebruiken. Zie het Overzicht van gekoppelde eigenschappenvoor meer informatie over gekoppelde eigenschappen.
Wat is een Storyboard?
Animaties zijn niet het enige nuttige type tijdlijn. Er zijn andere tijdlijnklassen beschikbaar waarmee u sets tijdlijnen kunt ordenen en tijdlijnen kunt toepassen op eigenschappen. Containertijdlijnen zijn afgeleid van de klasse TimelineGroup en bevatten ParallelTimeline en Storyboard.
Een Storyboard is een type containertijdlijn die gerichte informatie biedt voor de tijdlijnen die deze bevat. Een Storyboard kan elk type Timelinebevatten, inclusief andere containertijdlijnen en animaties. Met Storyboard-objecten kunt u tijdlijnen combineren die van invloed zijn op verschillende objecten en eigenschappen in één tijdlijnboom, zodat u eenvoudig complexe timinggedragingen kunt ordenen en beheren. Stel dat u een knop wilt waarmee deze drie dingen worden uitgevoerd.
De kleur vergroten en wijzigen wanneer de gebruiker de knop selecteert.
Verklein en ga vervolgens terug naar de oorspronkelijke grootte wanneer erop wordt geklikt.
Verkleinen en vervagen tot 50 procent ondoorzichtigheid wanneer deze wordt uitgeschakeld.
In dit geval hebt u meerdere sets animaties die van toepassing zijn op hetzelfde object en wilt u op verschillende momenten afspelen, afhankelijk van de status van de knop. Met Storyboard objecten kunt u animaties ordenen en in groepen toepassen op één of meer objecten.
Waar kunt u een Storyboard gebruiken
Een Storyboard kan worden gebruikt voor het animeren van afhankelijkheidseigenschappen van animatabelklassen (zie de Animatieoverzichtvoor meer informatie over wat een klasse animatabel maakt). Omdat storyboarding echter een functie op frameworkniveau is, moet het object behoren tot de NameScope van een FrameworkElement of een FrameworkContentElement.
U kunt bijvoorbeeld een Storyboard gebruiken om het volgende te doen:
Animatie toepassen op een SolidColorBrush (niet-framework-element) waarmee de achtergrond van een knop (een type FrameworkElement) wordt geschilderd ),
Animatie toepassen op een SolidColorBrush (niet-frameworkelement) die de opvulling van een GeometryDrawing (niet-frameworkelement) schildert die wordt weergegeven met behulp van een Image (FrameworkElement).
Animeer in code een SolidColorBrush die is gedeclareerd door een klasse die ook een FrameworkElementbevat, als de SolidColorBrush zijn naam heeft geregistreerd bij die FrameworkElement.
U kunt echter geen Storyboard gebruiken om een SolidColorBrush te animeren die de naam niet heeft geregistreerd bij een FrameworkElement of FrameworkContentElement, of niet is gebruikt om een eigenschap van een FrameworkElement of FrameworkContentElementin te stellen.
Animaties toepassen met een Storyboard
Als u een Storyboard wilt gebruiken om animaties te organiseren en toe te passen, voegt u de animaties toe als subtijdlijnen van de Storyboard. De klasse Storyboard biedt de gekoppelde eigenschappen Storyboard.TargetName en Storyboard.TargetProperty. U stelt deze eigenschappen in op een animatie om het doelobject en de eigenschap ervan op te geven.
Als u animaties wilt toepassen op hun doelen, begint u met de Storyboard met behulp van een triggeractie of een methode. In XAML gebruikt u een BeginStoryboard-object met een EventTrigger, Triggerof DataTrigger. In code kunt u ook de methode Begin gebruiken.
In de volgende tabel ziet u de verschillende plaatsen waar elke Storyboard begintechniek wordt ondersteund: per exemplaar, stijl, besturingssjabloon en gegevenssjabloon. 'Per exemplaar' verwijst naar de techniek van het rechtstreeks toepassen van een animatie of storyboard op exemplaren van een object, in plaats van in een stijl, besturingssjabloon of gegevenssjabloon.
Storyboard is begonnen met het gebruik van... | Per geval | Stijl | Sjabloon voor besturingselementen | Gegevenssjabloon | Voorbeeld |
---|---|---|---|---|---|
BeginStoryboard en een EventTrigger | Ja | Ja | Ja | Ja | Een Eigenschap Animeren met behulp van een Storyboard |
BeginStoryboard en een eigenschap Trigger | Nee | Ja | Ja | Ja | een animatie activeren wanneer een eigenschapswaarde verandert |
BeginStoryboard en een eigenschap MultiTrigger | Nee | Ja | Ja | Ja | voorbeeld van MultiTrigger-klasse |
BeginStoryboard en een DataTrigger | Nee | Ja | Ja | Ja | Instructies: een animatie activeren wanneer gegevens worden gewijzigd |
BeginStoryboard en een MultiDataTrigger | Nee | Ja | Ja | Ja | voorbeeld van MultiDataTrigger-klasse |
methode Begin | Ja | Nee | Nee | Nee | Een eigenschap animeren met behulp van een Storyboard |
In het volgende voorbeeld wordt een Storyboard gebruikt om de Width van een Rectangle-element te animeren en de Color van een SolidColorBrush dat wordt gebruikt om die Rectanglete schilderen.
<!-- 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;
}
}
}
In de volgende secties worden de TargetName- en TargetProperty gekoppelde eigenschappen gedetailleerder beschreven.
Framework-elementen, Framework-inhoudselementen en Freezables targeten
In de vorige sectie is vermeld dat een animatie, om zijn doel te vinden, de naam van het doel en de eigenschap om te animeren moet kennen. Het opgeven van de eigenschap voor animatie is eenvoudig: stel TargetProperty
in met de naam van de eigenschap om te animeren. U geeft de naam op van het object waarvan u de eigenschap wilt animeren door de eigenschap Storyboard.TargetName in de animatie in te stellen.
Voorzichtigheid
Hoewel u de eigenschap Target
kunt gebruiken om rechtstreeks aan een object te binden als alternatief voor TargetName
, is deze niet serialiseerbaar. Er is geen garantie dat het Target
object correct kan worden verwezen in XAML.
De eigenschap TargetName werkt alleen als het doelobject een naam heeft. Het toewijzen van een naam aan een FrameworkElement of een FrameworkContentElement in XAML verschilt van het toewijzen van een naam aan een Freezable-object.
Framework-elementen zijn klassen die overnemen van de FrameworkElement-klasse. Voorbeelden van frameworkelementen zijn Window, DockPanel, Buttonen Rectangle. In wezen zijn alle vensters, panelen en besturingselementen elementen. Framework-inhoudselementen zijn klassen die overnemen van de FrameworkContentElement-klasse. Voorbeelden van frameworkinhoudselementen zijn FlowDocument en Paragraph. Als u niet zeker weet of een type een frameworkelement of een frameworkinhoudselement is, controleert u of het een naameigenschap heeft. Als dit het geval is, is het waarschijnlijk een frameworkelement of een frameworkinhoudselement. Controleer de sectie Overnamehiërarchie van de bijbehorende typepagina om er zeker van te zijn.
Om het richten op een frameworkelement of een frameworkinhoudselement in XAML mogelijk te maken, stelt u de eigenschap Name ervan in. In code moet u ook de RegisterName methode gebruiken om de naam van het element te registreren bij het element waarvoor u een NameScopehebt gemaakt.
In het volgende voorbeeld wordt de naam MyRectangle
toegewezen aan Rectangle, een type FrameworkElement, uit het voorgaande voorbeeld.
<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);
Nadat deze een naam heeft, kunt u een eigenschap van dat element animeren.
<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 typen zijn klassen die overnemen van de Freezable-klasse. Voorbeelden van Freezable zijn SolidColorBrush, RotateTransformen GradientStop.
Om het targeten van een Freezable door een animatie in XAML mogelijk te maken, gebruikt u de x:Name Directive om het een naam te geven. In code gebruikt u de methode RegisterName om de naam te registreren bij het element waarvoor u een NameScopehebt gemaakt.
In het volgende voorbeeld wordt een naam toegewezen aan een Freezable-object.
<SolidColorBrush x:Name="MySolidColorBrush" Color="Blue" />
SolidColorBrush mySolidColorBrush = new SolidColorBrush(Colors.Blue);
this.RegisterName("MySolidColorBrush", mySolidColorBrush);
Vervolgens kan het object worden gebruikt in een animatie.
<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 objecten gebruiken naamscope om de eigenschap TargetName op te lossen. Zie WPF XAML Namescopesvoor meer informatie over WPF-naambereiken. Als de eigenschap TargetName wordt weggelaten, is de animatie gericht op het element waarop het is gedefinieerd, of, in het geval van stijlen, het gestijlde element.
Soms kan een naam niet worden toegewezen aan een Freezable-object. Als een Freezable bijvoorbeeld wordt gedeclareerd als een resource of wordt gebruikt om een eigenschapswaarde in een stijl in te stellen, kan deze geen naam krijgen. Omdat deze geen naam heeft, kan het niet rechtstreeks worden gericht, maar kan het indirect worden gericht. In de volgende secties wordt beschreven hoe u indirecte targeting gebruikt.
Indirecte doelgerichtheid
Er zijn momenten waarop een Freezable niet rechtstreeks door een animatie kan worden gericht, bijvoorbeeld wanneer de Freezable wordt gedeclareerd als een resource of wordt gebruikt om een eigenschapswaarde in een stijl in te stellen. In dergelijke gevallen kunt u, ook al kunt u het niet rechtstreeks richten, het Freezable-object nog steeds animeren. In plaats van de eigenschap TargetName in te stellen met de naam van de Freezable, geeft u deze de naam op van het element waartoe de Freezable behoort. Een SolidColorBrush die wordt gebruikt om de Fill van een rechthoekelement in te stellen, behoort bijvoorbeeld tot die rechthoek. Als u de kwast wilt animeren, stelt u de TargetProperty van de animatie in met een keten van eigenschappen die begint bij de eigenschap van het frameworkelement of frameworkinhoudselement waar de Freezable voor is gebruikt en eindigt met de eigenschap Freezable die geanimeerd moet worden.
<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);
Merk op dat, als de Freezable is bevroren, er een kloon zal worden gemaakt en die kloon zal worden geanimeerd. Als dit gebeurt, blijft de eigenschap HasAnimatedProperties van het oorspronkelijke object false
retourneren, omdat het oorspronkelijke object niet daadwerkelijk is geanimeerd. Zie de Freezable Objects Overviewvoor meer informatie over klonen.
Houd er ook rekening mee dat wanneer u indirecte eigenschapsdoelstelling gebruikt, het mogelijk is om objecten te targeten die niet bestaan. U kunt er bijvoorbeeld van uitgaan dat de Background van een bepaalde knop is ingesteld met een SolidColorBrush en de kleur ervan probeert te animeren, terwijl in feite een LinearGradientBrush is gebruikt om de achtergrond van de knop in te stellen. In deze gevallen wordt er geen uitzondering gegenereerd; de animatie heeft geen zichtbaar effect omdat LinearGradientBrush niet reageert op wijzigingen in de eigenschap Color.
In de volgende secties wordt de syntaxis voor indirecte eigenschaptargeting in meer detail beschreven.
Indirect richten op een eigenschap van een Freezable in XAML
Gebruik de volgende syntaxis om een eigenschap van een freezable in XAML te targeten.
Syntaxis van eigenschap |
---|
ElementEigenschapsNaam. BevriesbareEigenschapsNaam |
Waar
ElementPropertyName is de eigenschap van de FrameworkElement waarvoor de Freezable wordt gebruikt om in te stellen, en
FreezablePropertyName is de eigenschap van de Freezable om animatie toe te passen.
De volgende code laat zien hoe u de Color van een SolidColorBrush kunt animeren die wordt gebruikt om het Fill van een rechthoekelement in te stellen.
<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>
Soms moet u gericht zijn op een bevriesbaar object in een verzameling of tabel.
U gebruikt de volgende padsyntaxis om een bevriesbaar object in een verzameling te richten.
Padsyntaxis |
---|
ElementPropertyName.Children[ CollectionIndex]. FreezablePropertyName |
Waarbij CollectionIndex de index van het object in de matrix of verzameling is.
Stel dat voor een rechthoek een TransformGroup resource is toegepast op de eigenschap RenderTransform en u een animatie wilt toepassen op een van de transformaties die deze bevat.
<TransformGroup x:Key="MyTransformGroupResource"
x:Shared="False">
<ScaleTransform />
<RotateTransform />
</TransformGroup>
De volgende code laat zien hoe u de eigenschap Angle van de RotateTransform in het vorige voorbeeld kunt animeren.
<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>
Indirect doelgericht op een eigenschap van een freezable in de code
In code maakt u een PropertyPath-object. Wanneer u de PropertyPathmaakt, geeft u een Path en PathParametersop.
Als u PathParameterswilt maken, maakt u een matrix van het type DependencyProperty die een lijst met velden voor de eigenschaps-id van afhankelijkheden bevat. Het eerste id-veld is voor de eigenschap van de FrameworkElement of FrameworkContentElement waarvoor de Freezable wordt gebruikt om deze in te stellen. Het volgende id-veld vertegenwoordigt de eigenschap van de Freezable waarop moet worden gericht. U kunt het beschouwen als een keten van eigenschappen die de Freezable verbinden met het FrameworkElement-object.
Hier volgt een voorbeeld van een afhankelijkheidseigenschapsketen die is gericht op de Color van een SolidColorBrush die wordt gebruikt om de Fill van een rechthoekelement in te stellen.
DependencyProperty[] propertyChain =
new DependencyProperty[]
{Rectangle.FillProperty, SolidColorBrush.ColorProperty};
U moet ook een Pathopgeven. Een Path is een String die de Path vertelt hoe PathParameterste interpreteren. Hierbij wordt de volgende syntaxis gebruikt.
Syntaxis van eigenschapspad |
---|
(
OwnerPropertyArrayIndex).( FreezablePropertyArrayIndex) |
Waar
OwnerPropertyArrayIndex is de index van de DependencyProperty matrix die de id bevat van de eigenschap van het FrameworkElement-object dat de Freezable wordt gebruikt om in te stellen, en
FreezablePropertyArrayIndex is de index van de DependencyProperty matrix die de id van de eigenschap bevat die moet worden gericht.
In het volgende voorbeeld ziet u de Path die hoort bij de PathParameters die in het voorgaande voorbeeld is gedefinieerd.
DependencyProperty[] propertyChain =
new DependencyProperty[]
{Rectangle.FillProperty, SolidColorBrush.ColorProperty};
string thePath = "(0).(1)";
In het volgende voorbeeld wordt de code uit de vorige voorbeelden gecombineerd om de Color van een SolidColorBrush te animeren, die wordt gebruikt om de Fill van een rechthoek element in te stellen.
// 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);
Soms moet u zich richten op een freezable in een verzameling of matrix. Stel je voor dat een rechthoek een TransformGroup resource op zijn eigenschap RenderTransform heeft toegepast, en je wilt een van de transformaties die het bevat animeren.
<TransformGroup x:Key="MyTransformGroupResource"
x:Shared="False">
<ScaleTransform />
<RotateTransform />
</TransformGroup>
Als u een Freezable in een verzameling wilt toepassen, gebruikt u de volgende padsyntaxis.
Padsyntaxis |
---|
(
OwnerPropertyArrayIndex).( CollectionChildrenPropertyArrayIndex) [ CollectionIndex].( FreezablePropertyArrayIndex) |
Waarbij CollectionIndex de index van het object in de matrix of verzameling is.
Om de eigenschap Angle van de RotateTransformte richten, gebruikt u de tweede transformatie in de TransformGroupen de volgende Path en 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);
Het volgende voorbeeld toont de complete code voor het animeren van de Angle van een RotateTransform die zich in een TransformGroupbevindt.
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);
Indirect richten op een freezable als startpunt
In de vorige secties wordt beschreven hoe u een Freezable indirect kunt aansturen door te beginnen met een FrameworkElement of FrameworkContentElement en een eigenschapketen te maken voor een Freezable subeigenschap. U kunt ook een Freezable gebruiken als uitgangspunt en indirect gericht zijn op een van de Freezable subeigenschappen. Een extra beperking geldt bij het gebruik van een Freezable als uitgangspunt voor indirecte targeting: de begin-Freezable en elke Freezable ertussen en de indirect gerichte subeigenschap mogen niet bevroren zijn.
Interactief een Storyboard beheren in XAML
Als u een storyboard wilt starten in Extensible Application Markup Language (XAML), gebruikt u een BeginStoryboard triggeractie. BeginStoryboard distribueert de animaties naar de objecten en eigenschappen die ze animeren, en start het storyboard. (Zie het overzicht van het Animatie- en tijdsinstellingensysteemvoor meer informatie over dit proces.) Als u de BeginStoryboard een naam geeft door de bijbehorende eigenschap Name op te geven, maakt u het een besturingselement voor het storyboard. Vervolgens kunt u het storyboard interactief beheren nadat het is gestart. Hier volgt een lijst met besturingsbare storyboard-acties die u gebruikt met gebeurtenistriggers om een storyboard te beheren.
PauseStoryboard: hiermee wordt het storyboard onderbroken.
ResumeStoryboard: hervat een onderbroken storyboard.
SetStoryboardSpeedRatio: hiermee wordt de snelheid van het storyboard gewijzigd.
SkipStoryboardToFill: Hiermee wordt een storyboard naar het einde van de opvulperiode gebracht, als deze er een heeft.
StopStoryboard: Stopt het storyboard.
RemoveStoryboard: Hiermee verwijdert u het storyboard.
In het volgende voorbeeld worden besturingsbare storyboard-acties gebruikt om interactief een storyboard te beheren.
<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>
Interactief een Storyboard beheren met behulp van code
In de vorige voorbeelden ziet u hoe u animaties kunt toepassen met behulp van triggeracties. In code kunt u ook een storyboard beheren met behulp van interactieve methoden van de Storyboard-klasse. Als u een Storyboard interactief wilt maken in code, moet u de juiste overload van de Begin-methode van het storyboard gebruiken en true
opgeven om deze bestuurbaar te maken. Zie de pagina Begin(FrameworkElement, Boolean) voor meer informatie.
In de volgende lijst ziet u de methoden die kunnen worden gebruikt om een Storyboard te bewerken nadat deze is gestart:
Het voordeel van het gebruik van deze methoden is dat u geen Trigger of TriggerAction-objecten hoeft te maken; u hebt alleen een referentie nodig naar de controleerbare Storyboard die u wilt bewerken.
Notitie
Alle interactieve acties die worden uitgevoerd op een Clock, en dus ook op een Storyboard, zullen plaatsvinden tijdens de volgende cyclus van de timing-engine, die kort voor de volgende render plaatsvindt. Als u bijvoorbeeld de methode Seek gebruikt om naar een ander punt in een animatie te gaan, verandert de eigenschapswaarde niet direct, in plaats daarvan verandert de waarde op het volgende vinkje van de timing-engine.
In het volgende voorbeeld ziet u hoe u animaties toepast en beheert met behulp van de interactieve methoden van de Storyboard-klasse.
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
Animeer in een stijl
U kunt Storyboard objecten gebruiken om animaties in een Stylete definiëren. Een animatie toevoegen aan een Storyboard in een Style is vergelijkbaar met het gebruik van een Storyboard op een andere plek, met de volgende drie uitzonderingen:
U geeft geen TargetNameop; het Storyboard is altijd gericht op het element waarop de Style wordt toegepast. Om Freezable-objecten aan te spreken, moet u gebruik maken van indirecte targeting. Zie de sectie Indirect targeting voor meer informatie over indirecte targeting.
U kunt geen SourceName opgeven voor een EventTrigger of een Trigger.
U kunt geen dynamische bronverwijzingen of expressies voor gegevensbinding gebruiken om Storyboard- of animatie-eigenschapswaarden in te stellen. Dat komt doordat alles binnen een Style thread-veilig moet zijn en het timingsysteem objecten moet FreezeStoryboard om ze thread-veilig te maken. Een Storyboard kan niet worden bevroren als het of zijn kindtijdlijnen dynamische bronverwijzingen of expressies voor gegevenskoppelingen bevatten. Zie voor meer informatie over het bevriezen en andere kenmerken van Freezable het Overzicht van bevriesbare objecten.
In XAML kunt u geen gebeurtenis-handlers declareren voor Storyboard- of animatie-gebeurtenissen.
Zie het voorbeeld "Animatie toepassen in een stijl" voor een illustratie van hoe een storyboard in een stijl te definiëren.
Animatie toepassen in een ControlTemplate
U kunt Storyboard objecten gebruiken om animaties in een ControlTemplatete definiëren. Animatie toepassen op een Storyboard in een ControlTemplate is vergelijkbaar met het gebruik van een Storyboard elders, met de volgende twee uitzonderingen:
De TargetName mag alleen verwijzen naar onderliggende objecten van de ControlTemplate. Als TargetName niet is opgegeven, is de animatie gericht op het element waarop de ControlTemplate wordt toegepast.
De SourceName voor een EventTrigger of een Trigger mag alleen verwijzen naar kinderobjecten van de ControlTemplate.
U kunt geen dynamische bronverwijzingen of expressies voor gegevensbinding gebruiken om Storyboard- of animatie-eigenschapswaarden in te stellen. Dat komt doordat alles binnen een ControlTemplate thread-veilig moet zijn en het timingsysteem objecten moet FreezeStoryboard om ze thread-veilig te maken. Een Storyboard kan niet worden bevroren als het of zijn kindtijdlijnen dynamische bronverwijzingen of gegevensbindexpressies bevatten. Zie het Overzicht van bevriesbare objectenvoor meer informatie over het bevriezen en andere functies van Freezable.
In XAML kunt u geen gebeurtenis-handlers declareren voor Storyboard- of animatie-gebeurtenissen.
Zie de Voorbeeld van animatie in een ControlTemplate om te zien hoe u een storyboard in een ControlTemplatedefinieert.
Animatie toepassen wanneer een eigenschapswaarde wordt gewijzigd
In stijlen en besturingssjablonen kunt u Trigger-objecten gebruiken om een storyboard te starten wanneer een eigenschap wordt gewijzigd. Voor voorbeelden, zie Activeer een animatie wanneer een eigenschapswaarde verandert en animeer in een ControlTemplate .
Animaties die door objecten met eigenschap Trigger worden toegepast, gedragen zich op een complexere manier dan EventTrigger-animaties of animaties die zijn gestart met Storyboard methoden. Ze dragen over met animaties die zijn gedefinieerd door andere Trigger objecten, maar combineren met EventTrigger en door methoden geactiveerde animaties.
Zie ook
- Overzicht van animaties
- Overzicht van eigenschapsanimatietechnieken
- Overzicht van Freezable Objecten
.NET Desktop feedback