Click here to Skip to main content
6,822,123 members and growing! (18,012 online)
Email Password   helpLost your password?
Web Development » Silverlight » Controls     Beginner License: The Code Project Open License (CPOL)

Customizable Loading Indicator for Silverlight 3

By Eugene Pankov

An article on creating a customizable loading indicator for Silverlight 3
C# (C#3.0), Windows, .NET (.NET3.5), Silverlight, Dev
Revision:2 (See All)
Posted:25 Nov 2009
Updated:8 Dec 2009
Views:5,009
Bookmarked:39 times
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
9 votes for this article.
Popularity: 4.47 Rating: 4.68 out of 5

1

2
1 vote, 11.1%
3
1 vote, 11.1%
4
7 votes, 77.8%
5
Loading Indicators

Introduction

As it often happens, when you really need something - you can't find it. I needed a simple loading indicator for my Silverlight 3.0 application, something like a spinning wheel. And I found a few, but... some of them were too complex, some - pretty hard to customize. Finally, I decided to write my own control - very typical story for this community, yeah?

Background

A few words about what I planned to create. First of all, it should be a simple, customizable control. The only limitation - I didn't want to hard code its geometry, a shape of animated element. This element (PART_AnimationElement) is defined in the Generic.xaml file, but can be redefined as a part of a user's Style.

If you look at the Generic.xaml, you will see only one animation element - Ellipse. The problem was to manifold it. I was surprised to know that deep object cloning is a challenging task in Silverlight. If it takes three lines of code in WPF (here is a link to an example), there is no simple solution for Silverlight. Finally, I found a nice article "Professional Drag and Drop Manager Control for Silverlight 2" by Thilo Ruppert. He refactored a bit of code, written by Tamir Khason. I borrowed their code for DependencyPropertyCloner.

So, now we have an animation element and we know how to make copies. Let's see how it works.

How It Works

Download my demo solution and open it in Visual Studio. Here is its structure:

LoadingIndicator Solution

Loading Indicator is defined in the JP.UI.Controls project. It contains the following files:

LoadingIndicator.cs Defines behavior of the control.
DependencyPropertyCloner.cs Clones Dependency Objects. Used to copy animation elements.
Generic.xaml Defines default template of the control.

Let's look at the Generic.xaml first:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:JP.UI.Controls">


    <Style TargetType="local:LoadingIndicator">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:LoadingIndicator">

                    <!-- Template's Root Visual -->
                    <Canvas x:Name="LayoutRoot" Background="{TemplateBinding Background}">

                        <Ellipse x:Name="PART_AnimationElement" Width="12" 
				Height="12" Fill="{TemplateBinding Foreground}" />

                    </Canvas>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

Pay attention to two elements named LayoutRoot and PART_AnimationElement. If you are going to define your own style for the control, both elements shall exist in your template. Each time the control applies a style, it tries to find these elements:

/// <summary>
/// Builds the visual tree when a new template is applied.
/// </summary>
public override void OnApplyTemplate()
{
    base.OnApplyTemplate();

    LayoutRoot = GetTemplateChild("LayoutRoot") as Canvas;
    if (LayoutRoot == null)
    {
        throw new NotImplementedException
	("Template Part LayoutRoot is required to display LoadingIndicator.");
    }

    AnimationElement = GetTemplateChild("PART_AnimationElement") as FrameworkElement;
    if (AnimationElement == null)
    {
        throw new NotImplementedException("Template Part PART_AnimationElement 
		is required to display LoadingIndicator.");
    }

    CreateAnimation();
}

A Small Trick

Read the updated version of the article. Thanks to Aaginor - he pointed to a small problem. If you change visibility of the indicator to Collapsed, animation still runs, consuming resources. The first idea was to catch something like OnVisibilityChanged event, but you could hardly find such an event. Well, there is a LayoutUpdated event. And it definitely occurs when a control changes its visibility. But not only in this case.

That's why I decided to use a small trick - to create a private ControlVisibility property and bind it to the Visibility property of the control:

Binding binding = new Binding();
binding.Source = this;
binding.Path = new PropertyPath("Visibility");
this.SetBinding(LoadingIndicator.ControlVisibilityProperty, binding);

You can ask me: so what? Look at the definition of my ControlVisibilityProperty and you will find a ControlVisibilityCallback. That is an event handler calling every time the control changes its visibility. Nice place to stop animation when the indicator becomes invisible.

When you run the demo, you will see a "Hide/Show" button. It toggles visibility of the first control. I added it to check whether my code can really handle non existing OnVisibilityChanged event. It can!

Using the Code

Loading Indicator control has five public properties:

Count Number of animated elements. 12 by default.
Duration One animation cycle duration. One second by default.
Radius Inner radius of the indicator. 20 by default.
StartOpacity Start opacity of the animated element.
EndOpacity End opacity of the animated element.

Besides, Foreground property is used to fill animated elements. Look at the MainPage.xaml, creating four loading indicators, shown in the screenshot above. The first control uses built-in style, defined in the Generic.xaml. Three other controls use their own styles, defined in grid resources. I just want to note that Style1 uses a rectangle as an animated element.

You can try to experiment with different geometric figures, colors or gradients. I would be glad if you create your own fancy styles and share them with others in your comments to this article.

References

History

  • 24th November, 2009: Initial post
  • 8th December, 2009: Added "A Small Trick" section

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Eugene Pankov


Member
Eugene lives in Riga, Latvia. He started his programmer's career in 1983. Developed software for radio equipment CAD systems. Created computer graphics for TV. Worked in publishing houses. Developed Internet credit card processing systems for banks. Developed his own document management system. Now he is System Analyst in Accenture.
Occupation: Software Developer
Company: Accenture
Location: Latvia Latvia

Other popular Silverlight articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 7 of 7 (Total in Forum: 7) (Refresh)FirstPrevNext
GeneralYou can have a better code without using the DependencyPropertyClone... PinmemberNicolas Dorier1:43 17 Jan '10  
GeneralStupid simple PinmemberNicolas Dorier5:18 2 Dec '09  
GeneralA small change ... PinmemberAaginor0:10 1 Dec '09  
GeneralRe: A small change ... PinmemberEugene Pankov3:48 1 Dec '09  
GeneralRe: A small change ... PinmemberAaginor4:14 1 Dec '09  
GeneralPerfect Pinmemberdefwebserver11:58 30 Nov '09  
GeneralRe: Perfect PinmemberEugene Pankov21:45 30 Nov '09  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads.

PermaLink | Privacy | Terms of Use
Last Updated: 8 Dec 2009
Editor: Deeksha Shenoy
Copyright 2009 by Eugene Pankov
Everything else Copyright © CodeProject, 1999-2010
Web20 | Advertise on the Code Project