Splash screens and Loaders in Silverlight

Adding a loader or splash screen to your animation can add the final touch and bring all the elements together. This tutorial will teach you 3 different techniques to creating great loading screen. 
 
1. Progress Bars

2. Text percent loaded

3. Simple loading animation.

First steps

The first step is to set up your loading page and accompanying JavaScript file. Let’s call these SplashScreen.xaml and SplashScreen.js.  The SplashScreen.xaml will have all your visual elements and your JavaScript file will have code that updates your visual elements as the application loads.

To create your SplashScreen.xaml page, just open Notepad and paste this code in:

<Canvas
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Name="parentCanvas"
        Width="245"
        Height="89"
        Background="#FF2B2B2B"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<Grid x:Name="LayoutRoot"/>
</Canvas>

Save the file as SplashScreen.xaml. Now open up Expression Blend, create a new project, and then add this new SplashScreen.xaml to the project, This will allow us to work on the file with a visual design surface.

We will get to the styling in Expression Blend in just a moment, but first we need to wire up the HTML of the project to use the new SplashScreen.xaml and JavaScript when loading the application. This is done by adding 2 new parameters to the mix:

<param name="splashscreensource" value="SplashScreen.xaml"/>
<param name="onSourceDownloadProgressChanged" value="onSourceDownloadProgressChanged" />|

And remember to reference your JavaScript file in the head of the HTML document.

<script type="text/javascript" src="SplashScreen.js"></script>

So now your application will use the new SplashScreen.xaml file as a loading/splash screen for your application.

Open up your JavaScript file and insert this code:

function onSourceDownloadProgressChanged(sender, eventArgs)
{
    sender.findName("StatusText").Text = 
       Math.round((eventArgs.progress * 1000)) / 10 + " percent loaded";
    sender.findName("ProgressBarTransform").ScaleY = eventArgs.progress * 158;
}

This function will be called every time the projects loading progress changes (onSourceDownloadProgressChanged). A .text event will update your text block. You’ll notice a refrence to ProgressBarTransform, this isn’t the name of the Progress bar itself, but the name of the transform attached to it.

Now that we have our JavaScript file set up, let’s jump back over to Expression Blend and start styling our loader/splash screen.

Note: When creating your StatusText and ProgressBar, be sure to set your alignments to left and top, because these items will update dynamically, it will play havoc with your canvas size and creating some really interesting issues.

The Progress bar


The progress bar is a simple visual prompt to show users exactly how much of the application has loaded. This technique will use a parameter in the HTML called onSourceDownloadProgressChanged which will call a JavaScript file every time a little more of the application is downloaded. 

Here is my XAML for the Progress Bar: 

<Rectangle Height="39" Width="1" Canvas.Left="29" Canvas.Top="86" Stroke="#FF000000" RenderTransformOrigin="0,0.5" x:Name="ProgressBar" HorizontalAlignment="Left" VerticalAlignment="Top" StrokeThickness="0" Fill="#FF939393">
      <Rectangle.RenderTransform>
          <TransformGroup>
              <ScaleTransform x:Name="ProgressBarTransform" ScaleY="1" ScaleX="0"/>
              <SkewTransform/>
              <RotateTransform/>
              <TranslateTransform Y="49" X="0.5"/>
          </TransformGroup>
      </Rectangle.RenderTransform>
  </Rectangle>

The key points to note when creating a progress bar from scratch are to make sure your width is set to 1, your RenderTransformOrigin is set to left, and your X scale transform is set to 0 and has a name applied to it (so you can reference it in your JavaScript file).

Tip: If you want your loading bar to grow vertically, change your Y scale to 0 and X to 1. Then edit your JavaScript file to change the ScaleY value.

sender.findName("ProgressBarTransform").ScaleY

If you wish to edit the final size of your Progress bar when it hits 100%, edit the eventArgs.progress * 100; value to a higher or lower number.

That’s it for the Progress Bar. Let’s look at creating a text based percentage now.

Showing Percent loaded


This is very similar to the progress bar, but instead of updating the size of a shape, it will update a text box with the percentage loaded.

We already have the function set up for this in our JavaScript file, so all we need to do now is create a textblock called StatusText. You don’t need any preset text, because the function will automatically change it to “# percent loaded.”

Tip: Open your JavaScript file and change the text in the quotation marks to something else.

Math.round((eventArgs.progress * 1000)) / 10 + "% of the application is loaded";

Adding Loading Animations


Creating  an animation is a little different. You can’t use the onSourceDownloadProgressChanged parameter to call an animation, because it restarts the animation every time more of the application is downloaded, giving the effect that it’s jittering and broken. Instead to create an animation that plays from start to finish, use an EventTrigger within your SplashScreen.xaml file. This allows you to begin an animation without needing a ‘code behind’ or JavaScript file. 

First, create your animation by pressing the “new StoryBoard” button. Once you have created your animation, open up the XAML view on the page. You will notice the animation is referenced at the top of the page as a resource and is called using its x:Name. We need to attach the StoryBoard directly to an object (preferably the object associated to it).

To achieve this create an event trigger and attach it to the object. I am adding my trigger to a rectangle. So I place this inside the <rectangle> tags.

This trigger is set to begin the story board when the rectangle is loaded, but you can change the Rectangle.Loaded function to any of the other interactions available to your object.

 <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>
       
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers>

Once the trigger is in place, there is still no animation present. You need to grab your story board from the top of the XAML and place it between the <StoryBoard> tags, remember not to double up with tags and if you are copying your code from the top, it will throw an error because there are duplicate x:Names in the project (you can delete the x:Name once its inside the trigger).

Note: If you cut your StoryBoard from the top of the page and paste it in your event trigger, it will no longer be available to edit as a normal StoryBoard. My suggestion is to keep the original and copy it into the trigger. Then delete it’s x:Name when in the trigger. Then if you need to change it later, it’s still available. You just need to copy across the new XAML to your trigger each time.

About the Author

Alex Knight

Alex is a Silverlight MVP with a strong focus on the graphics and user interface side of things. He runs a Xamling with Jordan Knight (@jakkaj) which specialises in creating awesome experiences for Silverlight and WPF. So it doesn't matter what platform, if its xaml he digs it. If you want to find more out about Alex, check out:
AGKDesign.twitter | xamling.net

#1 Mark Monster on 6.15.2009 at 10:08 PM

Very interesting article Alex. I did never investigate this SplashScreen feature in detail. But I know at least know how to get started with it.

Do you know by any chance if those SplashScreens also work in SL3 Out-of-browser mode?

-

Mark Monster

#2 Alex Knight on 6.15.2009 at 10:19 PM

@ Mark Monster: I haven't actually played with the loaders and what effect OOB has on them. I have a feeling it might not work straight out of the box because of the loaders external nature to the application. So unless the application downloaded knows to grab all the other files to create the loader or the files are referenced by their full location, I just don't think this method would work.

Again I really don't know though, is something to look into soon for sure....

Thanks

Alex

#3 Philip Beadle on 6.16.2009 at 12:33 PM

Nice one Alex,

How would you do this using the ASP.Net Silverlight control?

#4 Jordan Knight on 6.16.2009 at 2:10 PM

Beadle Man,

the ASP Silverlight control has a SplashScreenSource attribute - I reckon that might be a good start.

#5 Ross Miles on 6.16.2009 at 2:20 PM

As Jordan said, you can add the two splash screen values to the tag.

e.g

<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/SilverlightApplication1.xap" MinimumVersion="2.0.31005.0" Width="100%" Height="100%" splashscreensource="~/ClientBin/SilverlightLoader1.xaml" onSourceDownloadProgressChanged= "onSourceDownloadProgressChanged" />

This will add the two parms to the outputted script.

#6 Alex Knight on 6.16.2009 at 2:22 PM

bet me to it ;)

#7 Rafe Kemmis on 6.16.2009 at 11:43 PM

Nice post Alex! I'm looking forward to trying this out!

#8 Jeroen Hartsuiker on 6.19.2009 at 4:31 AM

Just to be sure, is it in any way possible to reference/call your storyboard as a resource from your EventTrigger, like WPF:

<Window.Triggers>

<EventTrigger RoutedEvent="FrameworkElement.Loaded">

<BeginStoryboard Storyboard="{StaticResource Storyboard1}"/>

</EventTrigger>

<Window.Triggers>

So, do you always have to cut/copy your stotyboard from the resource to put it directly under your EventTrigger..?

#9 Alex Knight on 6.19.2009 at 9:18 AM

I don't see why that wouldn't work here, I haven't tried it myself but I think that would be a great way to do it and cut out the whole copy/paste method...

#10 Bharti on 6.26.2009 at 6:48 AM

Nice tutorial Alex.

Can you update source code for this.

#11 jon on 7.09.2009 at 3:12 AM

Hi.. Great stuff..

How do you add this the ASPX page - that hosts the SL app. Thanks in advance

#12 Alex Knight on 7.09.2009 at 9:02 AM

Hi Jon,

It depends on the version of Silverlight, for SL2 you need to create a web project with visual studio by setting a new Silverlight project which will create the web part of the project for you. If you are using Silverlight 3, when you create a new project in Expression Blend 3 you will create a web project with it automatically.

Hope that helps...

Thanks

Alex

#13 sulumits retsambew on 7.14.2009 at 2:59 PM

thanks for this nice info, it's so useful for me.

#14 Wolf Schmidt (MSFT) on 7.21.2009 at 6:04 AM

>> So, do you always have to cut/copy your stotyboard from the resource to put it directly under your EventTrigger..?

I believe the answer is yes. The issue is that {StaticResource} doesn't work under JavaScript. Per the original Silverlight 1.0 .Resources design it was just a place to park named storyboards, and the code that supports the javaScript programming model even under the updated runtime doesn't really go much beyond that. It gives a series of not very helpful errors if your XAML for a 1.0 app has {StaticResource} in it.

#15 Gonzalo on 12.10.2009 at 10:17 AM

Thanks Alex. This new Blog fixed my refresh browser crash on IE. No .xap anymore, just .xaml page ;)

Splashscreen now works smoothly.

www.gonzalomenoyo.com

#16 Alex Knight on 12.10.2009 at 12:14 PM

Fantastic I am happy I could help. Site is looking good to!

#17 Silas on 2.11.2010 at 8:12 PM

Hi Alex, thanks for sharing this - it was really useful and easy to understand!

#18 stamina RX on 2.18.2010 at 12:39 AM

thanks for this nice info, it's so useful for me.

Leave a Comment