![]() |
Web Development »
Silverlight »
Controls
Beginner
License: The Code Project Open License (CPOL)
Customizable Loading Indicator for Silverlight 3By Eugene PankovAn article on creating a customizable loading indicator for Silverlight 3 |
C# (C#3.0), Windows, .NET (.NET3.5), Silverlight, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
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?
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.
Download my demo solution and open it in Visual Studio. Here is its structure:
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();
}
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!
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.
| You must Sign In to use this message board. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
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 |