Falling Snow in Silverlight - Page 3
       by kirupa  |  19 December 2009

In the previous page, you added the FallingSnow behavior that does the magic needed to animate the snowflakes you added earlier. Unfortunately, it doesn't do that just yet, for there is one vital step that is missing - actually adding the behavior.

Adding the FallingSnow Behavior
To add the behavior, go back to MainPage.xaml and make sure your artboard with the snowflakes is visible. Looks in your Assets panel at click on the Behaviors node:

[ click on the Behaviors node in the Assets Library ]

Notice that one of the behaviors you see there is called FallingSnowBehavior! If you don't see it, be sure to build your project from the Project menu or press Ctrl + Shift + B.

Select the FallingSnowBehavior entry and drag-n-drop it onto your LayoutRoot directly on the artboard or via the Objects and Timeline panel:

[ drag and drop the behavior into your LayoutRoot ]

After you have dragged and dropped this behavior onto your LayoutRoot, press F5 or go to Project | Run to run your application. If the stars and planets are aligned just right, and they should be right now, you will find your snowflakes happily falling to the ground!

Take a break. Relax. Play a fun little game of Demolition City.

Overview of How Everything Works
Ok, let's continue. While you have a working version of the falling snow effect right now, we aren't quite done with this tutorial. A large part of what you did involved simply copying and pasting some code and dragging and dropping something in Blend without me providing any information on how everything fits in.

In a nutshell, here is our original problem - there are a lot of snowflakes that currently live inside a container that need to be animated to simulate falling snow.

There are a handful of ways you can accomplish that. One way that was presented to you in this tutorial is by using a behavior that you attach to your container itself, and this behavior contains everything needed to go through each snowflake and animate it. I describe behaviors in greater detail in my Introduction to Behaviors tutorial, but to summarize, a behavior is nothing more than some code you attach to an element.

Once a behavior is attached to the element, it has full freedom to manipulate the element and access any of its properties at will. It's beautifully parasitic when you think about it. The FallingSnowBehavior is designed to only work on a container/layout panel, and all layout panels have the ability to give you access to all of its children. The children in our case are the snowflakes that live inside it.

Our behavior, when it attaches to this layout panel (named LayoutRoot), instantly starts to go through its children and begins to perform the magic needed to make each snowflake fall. This magic is defined in code, so brace yourself - I'm going to explain how the code works.

All of the code we care about lives in FallingSnowBehavior.cs, so be sure to have it opened and let's get started:

public class FallingSnowBehavior : Behavior<Canvas>

With behaviors, while they can be placed on any DependencyObject (a fancy word for a whole lotta things), you can be more specific and constrain them to only be applicable to certain types of elements. In our case, we only want the behavior to work on layout panels that are Canvasses, so I specify Canvas here.

In case didn't notice this the first time through, if you go back to MainPage.xaml, notice that you can't actually drop your dragged FallingSnowBehavior behavior from the Asset library onto anything besides LayoutRoot, our Canvas. This line is what specifies that constraint.

private static Random randomNumber;

This line is fairly straightforward. I am declaring a static Random object called randomNumber. This will be used to generate the random values that each snowflake will have to give it (mostly) unique speed and radius.

protected override void OnAttached()
randomNumber = new Random();
this.AssociatedObject.Loaded += new RoutedEventHandler(ApplicationLoaded);

Every behavior will have this OnAttached method, and this method gets called when the behavior is properly hooked up to a parent and ready to go. Think of it as an official entry point for any code that you want to have excecuted.

Inside this method, the two lines you added are:

randomNumber = new Random();
this.AssociatedObject.Loaded += new RoutedEventHandler(ApplicationLoaded);

The first line initializes the randomNumber object you declared earlier. The second line is a bit more interesting.

When applications in Silverlight and WPF are run, a large amount of things are turned on inside the application. Not everything gets turned on at the same time, and you may run into cases where one part of your app is kicking and ready to go while another part that it depends on is still asleep. In these cases, your application will probably crash.

One way of avoiding this is to ensure that you only execute when everything has fully been loaded and turned on. That is handled by the Loaded event that I attach to the behavior's parent - known to friends as this.AssociatedObject. The behavior's parent in this case is actually our friendly Canvas called LayoutRoot.

As with most events, it needs to be associated with an event handler that will fire when the event fire. This Loaded event is no different, and it is associated with the ApplicationLoaded event handler that I will describe...on the next page!

Onwards to the next page!

 1 2 | 3 | 4


kirupa.com's fast and reliable hosting provided by Media Temple.