wpfintro7
< Continued from page 1
To add a Storyboard to the previous example, add these lines below the declaration of myDoubleAnimantion:
myStoryboard = New Storyboard()
myStoryboard.Children.Add(myDoubleAnimation)
Storyboard.SetTargetName(myDoubleAnimation, Label1.Name)
Storyboard.SetTargetProperty( _
myDoubleAnimation, _
New PropertyPath(Label.OpacityProperty)
Then, instead of using the BeginAnimation method, begin the Storyboard:
myStoryboard.Begin(Me)
Storyboards are another kind of Timeline that let organize the animations that you want to apply to an object. For example, you can use multiple sets of animations that apply to the same object. Notice that in the first animation, only one animation (myDoubleAnimation) can be used in the BeginAnimation method because it's passed as a parameter and there's only room for one. What if we want to vary the color and opacity of the Label at the same time? To do that, you need a Storyboard. To add another animation, just add another member of the Storyboard's Children.
This can be easier said than done. When Microsoft does it in a demo, it looks so easy. But when you try to do it at your computer, if you're like me, it's not so easy after all. To illustrate a little bit about how to find the right path up the WPF mountain, we're going to show a few false starts and how to figure out what's wrong and fix it.
Your first try might use the same pattern used earlier:
' This code does not work!!
Dim myColorAnimation As ColorAnimation = _
New ColorAnimation()
With myColorAnimation
.From = Colors.Red
.To = Colors.Green
.Duration = New Duration(TimeSpan.FromSeconds(10))
.AutoReverse = True
.RepeatBehavior = RepeatBehavior.Forever
End With
myStoryboard.Children.Add(myColorAnimation)
Storyboard.SetTargetName(myColorAnimation, Label1.Name)
Storyboard.SetTargetProperty( _
myColorAnimation, _
New PropertyPath(Label.ColorProperty))
' This code does not work!!
You discover that Label doesn't have a ColorProperty. Actually, changing the ColorProperty of a Label really doesn't make sense because a Label has a number of different properties that can have color. Foreground is the one that needs to be animated, but it doesn't have one either. But the tooltip that displays the error in Visual Studio suggests that an object from System.Windows.Media.Brush is what you want. If you change the statement to this ...
Storyboard.SetTargetProperty( _
myColorAnimation, _
New PropertyPath(SolidColorBrush.ColorProperty))
... then the code works again, but the color doesn't change! That's because nothing ties the SolidColorBrush to the Label. To do that, declare a SolidColorBrush in your code and use that to assign the color to the Label Foreground property.
Dim myAnimatedBrush As SolidColorBrush = _
New SolidColorBrush()
Label1.Foreground = myAnimatedBrush
You also have to make sure that this new SolidColorBrush is the object that is animated. This has to be a string and Intellisense tells you that it has to be the name of a . So you change the parameter of the SetTargetName like this:
Storyboard.SetTargetName(myColorAnimation, "myAnimatedBrush")
Now ... maybe we're ready. There are no syntax errors, so you try running it again. But, Nooooo! You get an InvalidOperationException:
'myAnimatedBrush' name cannot be found in the name scope of 'WpfApplication1.Window1'.
"Whaddayamean!!" you scream. "I just declared it a few statements earlier. It's gotta be in scope!!" Ah! You forgot that it has to be the name of a dependency object. Label, is a dependency object in the XAML code so all you had to do was reference it. But your SolidColorBrush doesn't have a name in the XAML!
Fortunately, WPF has a solution for this too. There's a way of assigning a name to the object in your code. Add this statement ...
Me.RegisterName("myAnimatedBrush", myAnimatedBrush)
... and you're finally good to go. Now when you click Run, you get what you're looking for. The opacity and the color both animate. You can download the code and run it yourself. Click Here to Download
The first animation we did (without the Storyboard) had to be done in VB.NET code because Framework 3.5 XAML doesn't quite yet have the required functionality. But this last one could be done completely in XAML without any VB.NET code at all. Many people feel that it's easier and faster to do things like this in XAML instead of code. That may be, but we're VB.NET programmers here; and part of the reason for creating WPF was to be able to give part of the job to designers. (They're supposed to do the XAML.)
WPF defines animation classes for 22 different types. In addition to ColorAnimation, you can use VectorAnimation, PointAnimation, and a lot more. It's a hugely powerful technology.
The final article uses the maximum number of pages allowed by my editor to get everything in. Here's Part 8: TripPlanner - A Complete WPF and XAML in Visual Basic.
To add a Storyboard to the previous example, add these lines below the declaration of myDoubleAnimantion:
myStoryboard = New Storyboard()
myStoryboard.Children.Add(myDoubleAnimation)
Storyboard.SetTargetName(myDoubleAnimation, Label1.Name)
Storyboard.SetTargetProperty( _
myDoubleAnimation, _
New PropertyPath(Label.OpacityProperty)
Then, instead of using the BeginAnimation method, begin the Storyboard:
myStoryboard.Begin(Me)
Storyboards are another kind of Timeline that let organize the animations that you want to apply to an object. For example, you can use multiple sets of animations that apply to the same object. Notice that in the first animation, only one animation (myDoubleAnimation) can be used in the BeginAnimation method because it's passed as a parameter and there's only room for one. What if we want to vary the color and opacity of the Label at the same time? To do that, you need a Storyboard. To add another animation, just add another member of the Storyboard's Children.
This can be easier said than done. When Microsoft does it in a demo, it looks so easy. But when you try to do it at your computer, if you're like me, it's not so easy after all. To illustrate a little bit about how to find the right path up the WPF mountain, we're going to show a few false starts and how to figure out what's wrong and fix it.
Your first try might use the same pattern used earlier:
' This code does not work!!
Dim myColorAnimation As ColorAnimation = _
New ColorAnimation()
With myColorAnimation
.From = Colors.Red
.To = Colors.Green
.Duration = New Duration(TimeSpan.FromSeconds(10))
.AutoReverse = True
.RepeatBehavior = RepeatBehavior.Forever
End With
myStoryboard.Children.Add(myColorAnimation)
Storyboard.SetTargetName(myColorAnimation, Label1.Name)
Storyboard.SetTargetProperty( _
myColorAnimation, _
New PropertyPath(Label.ColorProperty))
' This code does not work!!
You discover that Label doesn't have a ColorProperty. Actually, changing the ColorProperty of a Label really doesn't make sense because a Label has a number of different properties that can have color. Foreground is the one that needs to be animated, but it doesn't have one either. But the tooltip that displays the error in Visual Studio suggests that an object from System.Windows.Media.Brush is what you want. If you change the statement to this ...
Storyboard.SetTargetProperty( _
myColorAnimation, _
New PropertyPath(SolidColorBrush.ColorProperty))
... then the code works again, but the color doesn't change! That's because nothing ties the SolidColorBrush to the Label. To do that, declare a SolidColorBrush in your code and use that to assign the color to the Label Foreground property.
Dim myAnimatedBrush As SolidColorBrush = _
New SolidColorBrush()
Label1.Foreground = myAnimatedBrush
You also have to make sure that this new SolidColorBrush is the object that is animated. This has to be a string and Intellisense tells you that it has to be the name of a . So you change the parameter of the SetTargetName like this:
Storyboard.SetTargetName(myColorAnimation, "myAnimatedBrush")
Now ... maybe we're ready. There are no syntax errors, so you try running it again. But, Nooooo! You get an InvalidOperationException:
'myAnimatedBrush' name cannot be found in the name scope of 'WpfApplication1.Window1'.
"Whaddayamean!!" you scream. "I just declared it a few statements earlier. It's gotta be in scope!!" Ah! You forgot that it has to be the name of a dependency object. Label, is a dependency object in the XAML code so all you had to do was reference it. But your SolidColorBrush doesn't have a name in the XAML!
Fortunately, WPF has a solution for this too. There's a way of assigning a name to the object in your code. Add this statement ...
Me.RegisterName("myAnimatedBrush", myAnimatedBrush)
... and you're finally good to go. Now when you click Run, you get what you're looking for. The opacity and the color both animate. You can download the code and run it yourself. Click Here to Download
The first animation we did (without the Storyboard) had to be done in VB.NET code because Framework 3.5 XAML doesn't quite yet have the required functionality. But this last one could be done completely in XAML without any VB.NET code at all. Many people feel that it's easier and faster to do things like this in XAML instead of code. That may be, but we're VB.NET programmers here; and part of the reason for creating WPF was to be able to give part of the job to designers. (They're supposed to do the XAML.)
WPF defines animation classes for 22 different types. In addition to ColorAnimation, you can use VectorAnimation, PointAnimation, and a lot more. It's a hugely powerful technology.
The final article uses the maximum number of pages allowed by my editor to get everything in. Here's Part 8: TripPlanner - A Complete WPF and XAML in Visual Basic.