Lucky me! In the post during the week I received a copy of the new book by Charles Petzold - "3D Programming for Windows". I read his first book on WPF - "Applications = Code + Markup" and loved that and am really happy to start reading this book. Charles was kind enough to send me a copy for free and I am most grateful for this.
I sat down this morning with the book and started reading and it looks like a great book with a lot of content to consume. To those who didn't appreciate the fact that his previous WPF book came with no pictures, this one is full of them! I haven't touched on 3D at all in WPF since I've been busy with Silverlight 1.1 applications for a while so this will be a welcome change.
I could explain this all in my blog, but I think I might let someone called Scott Guthrie explain. He seems to know a bit about the announcement. ;)
Have you ever needed to create a timer in Silverlight? Without worrying too much about threading issues? Well, have no fear here is a quick and sneaky way to get this to work in your Silverlight application without much hassle.
In your C# (or in the XAML of the page) add a new storyboard:
1: StoryBoard timer = (Storyboard)XamlReader.Load(
2: "<Storyboard xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"
3: x:Name=\"TimerClick\" Duration="00:00:02 />");
4:
5: //Add a completed delegate to run code after the storyboard has completed
6: timer.Completed += new EventHandler(Timer_Completed);
7:
8: //Add the storyboard to the resources of the page
9: this.Resources.Add(timer);
If you remember from a previous post, a Storyboard as a Completed event. Using this, we can add a new delegate (Line 6) and hey presto, we have something quick and easy that acts as a timer for us.
Animations in Silverlight are dead easy. With a small amount of XAML you are easily able to make your application look amazing and show off your design skills. In some cases however, you want to step out of the XAML and into the world of managed C# and create some dynamic animations.
As an example in an application I'm currently busy with, I needed to dynamically create an animation on a Framework to create a snapping effect when dragging the element on the screen. This can easily be done in managed code by creating a StoryBoard object and adding DoubleAnimation objects to this storyboard. However, in the current release of Silverlight 1.1, creating animations using code causes runtime errors because of an inconvenient bug.
The work around is surprisingly easy. How do we do it? Simply create the animation as you would have done in XAML and load it into an object. Have a look below:
1: string storyboardName = "MyStoryBoard";
2: string myXamlElement = "MyXamlElement";
3:
4: int newLeftPosition = 120;
5:
6: Storyboard sb = XamlReader.Load(String.Format(
7: @"<Storyboard xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" x:Name=""{0}""> 8: <DoubleAnimation Storyboard.TargetName=""{1}"" 9: Storyboard.TargetProperty=""(Canvas.Left)""
10: To=""{2}"" Duration=""00:00:00.1200000""/> 11: </Storyboard>", storyboardName, myXamlElement , newLeftPosition )) as Storyboard;
12:
13: //Add a delegate to remove the storyboard from resources as soon as it is finished.
14: sb.Completed += delegate(object sender, EventArgs eventArgs)
15: { 16: this.Resources.Remove(sb);
17: };
18:
19: //Add to the resources of the page
20: this.Resources.Add(sb);
21:
22: //Begin the storyboard which will animate the element to the correct position.
23: sb.Begin();
The XamlReader object has a wonderful static method called Load() which takes in a string and returns a DependancyObject object which you can then cast to the StoryBoard element we know it is.
As you can see, this animation moves a target element to a new Canvas.Top position based on the number we pass into newLeftPosition. Because this is a dynamic resource, we don't want old animations hanging around in the resource dictionary. Luckily for us, we have a Completed event to hook into which as you can see on line 12, we remove the animation from the resources collection by using an inline delegate.
Not very elegant, but does solve our problem. Pretty nifty stuff!