A Wait Indicator In Silverlight

For my Silverlight Line-Of-Business framework I wanted a wait indicator much like there is in Firefox or when starting a Youtube video, which could indicate when the application is going off to the server to retrieve some data (or sending some back).  If you don’t know it, the style I’m talking about is eight dots in a circle that light up one after the other around the circle (see the screenshot below).  Funnily enough I couldn’t find any controls out there for this purpose, so initially I just used a text block to notify the user something was happening.  Now that I have a little more time I decided to revisit this and develop my own.  In fact I ended up developing three (that look identical but are implemented differently) in order to familiarise myself with animation in Silverlight, and compare the different approaches.

A bit of an overview of Silverlight animation first (as it pertains to this control with changing the colours of framework elements).  A storyboard is added to to the resources of the user control, and defines the animation per element (ie. each object to be animated – in this case each dot in the circle).  For each element you specify a number of key frames, which essentially consist of a time and the colour the fill of the element should have at that time.  In this case I am changing the alpha value of the fill colour to a specific value and specifying these values in 0.15 second intervals.  In between these 0.15 second intervals the Silverlight rendering engine continues to render the animation, interpolating the value of the previous key frame with that of the next key frame to gradually blend the previous key frame’s colour with that of the next key frame.

I first looked at implementing the animation directly in the XAML using a storyboard with a number of key frames.  I found this approach quite tedious (especially when I ran it and discovered it was animating in reverse – I had to rearrange 64 key frames manually to fix it).  It also blew out the size of my XAML file.  When I started building this control I wrapped the storyboard in an Event Trigger (when the canvas loaded) so that it would automatically start when the control was displayed.  One concern I had was whether the control would continue to animate even when it wasn’t visible (I’m not sure of the answer to this question as yet), and another was raised when in my research I came across this topic in the MSDN documentation that noted (in the remarks) that this approach was discouraged, and to instead put the storyboard in the UserControl.Resources section instead (and manually trigger the start of the animation):

http://msdn.microsoft.com/en-us/library/system.windows.eventtrigger(VS.95).aspx

So now I trigger the animation by including public methods on the control to start and stop the animation.  

Note that each dot in the circle is actually white, but we are just adjusting the alpha levels of each dot (blending in with whatever is behind) to give the impression of a moving dot with a trail.  By only altering the alpha value, this means is that you don’t have to use this control on a black background – any backdrop (including graphics) will work and look good.

Now to compare the three approaches.  The animation defined in XAML was painful to implement (it may be easier to do in Expression Blend but I was developing the XAML directly in the Visual Studio editor), whilst it was quite easy programatically (both methods).  Defining the storyboard in both the XAML page and code of course gave exactly the same look and speed as each other.  However manually handling the updating of each “frame” in code produces a slightly slower result (see the sample application to compare) which I found intriguing, despite the same key frame rate – it would be interesting to monitor this difference on a more intensive animation.  Of course I could increase the key frame rate (which is the duration of the animation in this implementation, so essentially reducing the duration) to match but I’m not particularly concerned in this scenario.  The other difference between the storyboard implementation and the  programmatic animation is that they actually look different (as you may note from the screenshot below):

Wait Indicator Sample App Screenshot

Notice when we are programmatically handling the updates that the “lead dot” is the brightest, whilst when the animation is handled by a storyboard the brightest dot isn’t the “lead dot”, but the second dot in the “bright dots” instead (if that makes sense).  This goes back to how the Silverlight rendering engine interpolates the values of the previous and the next key frame – this dot is supposed to be the dullest dot but it knows it is to be the brightest dot at the point of the next key frame so it’s “gearing up for it” by getting brighter as the next key frame approaches.  However in our programmatic updates we are changing the values “discretely” once every 0.15 seconds with no interpolation, thus the lead dot is always the brightest.

Another interesting aspect to compare was the size difference in the class libraries for each implementation.  As compiled DLLs, the XAML version came in at 14,848 bytes, defining the storyboard programmatically came in at 9,216 bytes, whilst the programmatic animation version came in at just 7,680 bytes.  My assumption here is that (and from inspecting each DLL in Reflector) that the XAML file is not compressed when added as a resource to the DLL, while the code in the programmatic version is “compiled” into a relatively compact intermediate language (MSIL) with the comments removed.  Of course this is not the whole story with Silverlight as the DLLs are packed into the .xap file in the main Silverlight project (which is compressed in the zip format).  So to compare this I zipped each DLL and compared the size of each zip file.  The result here was much closer – 3,185 bytes for the XAML version and 2,962 bytes for the programmatic animation – a difference of just 223 bytes, but programmatically defining the storyboard was the largest at 3,863 bytes.  So for this example at least you could say that the impact of each version on your XAML file is negligible.

I would welcome feedback on what approach you think is best and could be considered a “best practise” for implementing animation in Silverlight.  Whereas it was tedious to define the animation in XAML, it’s likely to be more easily modified in Expression Blend later, whilst the programmatic versions will have to always be altered via code.  You have 3 different versions of the control so you can choose your favourite, but until feedback tells me otherwise I will incorporate the version where the animation is defined in the XAML page in my LOB framework.

To use the control in your own projects (whichever version you choose) you could leave it in it’s own DLL (as it is currently) and just reference it from your project, or alternatively just include the .xaml and .cs files in your project.  I recommend changing the namespace (you’ll need to do this in both the .xaml file and the .cs file) as the current namespace name is really designed just for the sample application where the three different versions were running along side each other.  Then reference the namespace in the user control you want it to appear in with a prefix, and then reference and position the control in your xaml layout (remember to include a name for the control using the x:name attribute).  Then in your code behind you can call the Start() and Stop() methods on the control to start and stop the animation.  When the animation is stopped the circle of dots will be hidden, only appearing when the animation is running.

Note that there appears to be a bug in the RC0 version of Silverlight – when you use this control on a surface you won’t see a preview of it in the Visual Studio designer as I collapse the canvas until the animation has been started unless it is being hosted in the designer, using the following code:

System.ComponentModel.DesignerProperties.GetIsInDesignMode(this)

which doesn’t appear to pick up the fact that it is in design mode in the Visual Studio designer, so the canvas is collapsed anyway.

As a footnote, after writing the control I was browsing some Silverlight articles about the RC0 release and realised that the new progress bar control could potentially be used as a wait indicator animation also.  This control has a property called IsIndeterminate which if set to True does not render a standard progress bar but displays a moving gradient animation, so I have included this in the sample application for completeness.  I think my wait indicator control looks a whole lot better though (no doubt I’m biased however).

I hope you find this control useful!

Download

Advertisements

28 thoughts on “A Wait Indicator In Silverlight

  1. Hi Chris

    I used your wait indicator in a Silverlight application and it worked very well. However I have had to convert the application to WPF and I can’t get the indicator to animate. I have rebuilt the code as a WPF user control and the indicator appears but it does not animate. Any ideas why – everything seems as if it should work?

    • Hi Ian

      Sorry, I’ve no idea as I haven’t tried converting this control to WPF. It could depend on which version you use too (the XAML based one being the best). I’ve got a new version of this control with more features which I’ll post at some stage, but that won’t help you. So sorry, I don’t know off the top of my head…!

      Chris

      • Works great in SL 4. Trying it in WPF 4 throws an exception: Provide value on ‘System.Windows.Baml2006.TypeConverterMarkupExtension’ threw an exception.

        The issue is Storyboard.TargetProperty=”(Fill).(SolidBrush.Color)” in each ColorAnimationUsingKeyFrames. SL likes it but WPF does not. Changing it to Storyboard.TargetProperty=”(Fill).(Color)” allows the same template to be used in both.

      • Thanks for the feedback Bryce.I’ve been meaning to update this control for ages here, as it’s extremely popular, and it’s got another minor bug reported here in the comments by someone else. Most importantly, it’s only a user control (the version in the source code for my book is a proper custom control). I’m actually just updating the creating custom controls chapter of my book – I might include this change :). Thanks!

  2. Very nice – went directly into my project – Thanks !

    Just a small note:
    The XAML version is missing a Keyframe 1.20 to get a smooth animation – the value on this keyframe should be the same as the first keyframe.
    (did not check the other version)

    Lars

    • Wow, Lars – after having this up for over a year and having 100s of downloads you’re the first person to notice this (or tell me about it at least). I couldn’t see it initially, but when I set the SpeedRatio property on the Storyboard to 0.2 it became painfully obvious. Considering the amount of time I initially spent on creating and analysing this I can’t believe I didn’t notice it. Thanks for letting me know. It’s probably time I updated this for Silverlight 3 anyway (I had been meaning to do an update for a while with some new behaviour for binding nicely with the RIA Services’ data source). I’ll do a new post with the update when I get a chance in the next few days…

      Thanks

      Chris

  3. Hi Chris

    I was really glad when I found your waiting indicator for silverlight, since this is something I really need in my project. But I’m sorry to say that I cannot get the control to show up at all. I have added your dll file as reference and then I placed it on my xaml page and added the handlers to start the animation. Even though I can compile without any problem I cannot get the waitindicator to show up.

    Do you have any ideas of what could be the problem?

    (I use blend 3)

    Best Regards

    Magnus

    • Hi Magnus

      Sorry, I’m not sure. There are a multitude of reasons. That version (which I have changed a lot since then) needed to be run on a non-white background (because the “balls” were white). Would that be the case? I’m planning to release a newer version, but I have numerous balls in the air at the moment and absolutely no time to spare on side projects :(. Does the sample project run for you?

      Chris

    • No worries Magnus. The version I’m using now has grey dots instead of white. It would be no good on a grey background, but that’s less likely than a white or a black background. It shouldn’t be too hard to change though (change the white colour to grey), but the new version will come when I get a chance (hopefully soon)…

      Chris

  4. Hi Magnus (Chris)

    I also had a light background – It’s very easy to make it work – just change all 8 ColorAnimation/LinearColorKeyFrame values from

    to

    /Lars

  5. Or what Lars just said. Thanks Lars :). I just checked and the version where I had it on a white background I used 777777 (mid-grey) – although I think I changed the opacity values to suit. I’ll have to get the new version done and post it as I still get a lot of downloads for this control (it’s by far my most popular post + download), but in the meantime what’s here should give you a good start. Anyway, it’s good to see people find it useful…

    Chris

  6. first I thought that I just needed to change the colours of the elipse, but that didn’t have any effect at all, then I change the codebehind to this..

    keyFrame.Value = Color.FromArgb(alphaLevelsArray(ellipseIndex + ELLIPSE_COUNT – frameIndex), 0, 0, 0)

    Then it works on o white background. But then I thought that it would be nice to be able to be able to choose white or black fading dots. So I added a boolean value to the public properties. But for some reason that didn’t work…

    • Hi Magnus

      It sounds as though you are using one of the programmatic examples that I included. It’s probably better to stick to the XAML version, although you wouldn’t be able to set the colour of the dots with a property (well, not easily that is).

      Chris

  7. Hi Chris

    It doesn’t matter if I can’t set the values of the dots, but it would be great to be able to set white or black dots. I added this..

    _UseWhiteAnimation = UseWhiteAnimation

    DefineStoryboard()

    #Region “Public Functions”

    Private _UseWhiteAnimation As Boolean
    Public Property UseWhiteAnimation() As Boolean
    Get
    Return _UseWhiteAnimation
    End Get
    Set(ByVal value As Boolean)
    _UseWhiteAnimation = value
    End Set
    End Property

    But the UseWhiteAnimation does not retrieve any value, I’ missing something here….

    • Hey Rishi

      Thanks for your comment – I’m always glad to hear people are finding the control useful, and enjoy seeing how they use it. Nice work with the Sudoku app – if you add pencil marking functionality it will be fantastic! (I do a Sudoku myself every day). It’s certainly the best Silverlight Sudoku app I’ve seen!

      Chris

      • Thanks, and I will try n’ add the pencil marking and timer functionality to it when I get some time.. or maybe when I’m doing the iTablet version of it.. πŸ™‚

  8. Pingback: iPhone Sudoku in Silverlight using MVVM

  9. Hi Chris,

    I was wondering if you ever got a chance to convert this control to Silverlight 3. I have been trying today to get this control to work and realized it was using Silverlight 2.
    Can you please confirm?

    A very useful control for sure.

    Thanks,
    Surya

    • Hi Surya

      This control was written for Silverlight 2, but will work fine in Silverlight 3 and 4. It’s not perfect – I did it as a user control (better to be a custom control), and as mentioned earlier in the comments there was a frame missing from my animation. In the source code for my book (downloadable from the Apress site) you can find a Silverlight 4 version (that will work in Silverlight 3), written as a custom control, with the bug fixed, and some additional features.

      Hope this helps.

      Chris

  10. Hi Chris,
    Any ideas why sometimes the control does not animate? I have copied the xaml and code for the wait indicator into my own user control. In some places where I use it the animation works great. In other places, the control is visible, but the animation is not working. I know it is getting into the StartIt routine.

    Thanks

    • Hi Mary Ann

      I have seen that problem once myself, but I don’t know why that happens or whether there’s a solution (I didn’t end up investigating it, as it was just a small prototype). In all other instances it’s worked fine. I tend to focus on the business application side of Silverlight, so I’m not really up on the ins and outs of animations. In the instance I saw the problem, the application was doing a call to the server at the same time, but being performed asynchronously shouldn’t have affected it. It might be worth posting as a question on StackOverflow – I’m sure someone there will have an answer. I regularly monitor the posts there tagged with Silverlight, so I will keep an eye out for it. It might help if you can create a small application that reproduces the problem which you can link to your question there.

      Chris

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s