Introduction
This provides a free user control to denote progress of anything in your application. You can use the WPF provided Progress Bar, but this is another way of showing the progress, kind of different.
Background
I used this control to show progress of a Asynchronous Query on the server. This Progress Ring control starts rotating when the Fire Query button is clicked. If the Query fails, then this control shows red color, else in case of success it shows green.
I also used this control to show progress of a huge server side processing. As I found it useful in two of my applications, I pasted the code here so that you can use it too.
This also explains using EventTriggers and Animation in XAML.
Using the Code
Let's check the XAML.
The Ring
The main Ring is constituted of a Path which has two gradient stops. One is dark and another is light. This was created in Expression Blend by combining to concentric circles, filling them with a Gradient color and then combining them as a Path. Simple!
<Path Stretch="Fill" Stroke="#7F505096" Data="M100,63.5 ... 96.565479,0.5 100,0.5 z"
Name="ringPath" RenderTransformOrigin="0.5,0.5">
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1"/>
<SkewTransform AngleX="0" AngleY="0"/>
<RotateTransform Angle="0"/>
<TranslateTransform X="0" Y="0"/>
</TransformGroup>
</Path.RenderTransform>
<Path.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop x:Name="GradientStop1" Color="Blue" Offset="0"/>
<GradientStop x:Name="GradientStop2" Color="LightBlue" Offset="1"/>
</LinearGradientBrush>
</Path.Fill>
</Path>
Rotation Animation
The animation you see is because we rotate this Path from 0 to 360 degrees and the Gradient colors rotate as a result and visually we see the revolution of ring. The rotateAnimation
in Resources
section of XAML has the markup to rotate as below:
<Storyboard x:Key="rotateAnimation">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ringPath"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)
[2].(RotateTransform.Angle)" RepeatBehavior="Forever">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="360"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
Color Change Animation
For each state, a different color animation is defined. The color animation changes the Gradient Color Stops of the ring to the appropriate color. With every state change, a different event trigger is fired. Let's take the ErrorState
animation:
<Storyboard x:Key="errorStateAnimation">
<ColorAnimation
Storyboard.TargetName="GradientStop1"
Storyboard.TargetProperty="Color"
From="White" To="Red"
Duration="0:0:0.5"
BeginTime="0:0:0">
</ColorAnimation>
<ColorAnimation
Storyboard.TargetName="GradientStop2"
Storyboard.TargetProperty="Color"
From="White" To="DarkRed"
Duration="0:0:0.5"
BeginTime="0:0:0" />
</Storyboard>
This changes the light Gradient Stop to Light Red and the dark Gradient Stop to Dark Red color. When a error event trigger is fired, the color will thus change to Shades of Red with an animation.
Event Trigger
When each event trigger if fired, it starts the appropriate animation. Let's take the Executing State Event:
<EventTrigger RoutedEvent="local:QueryStatus.ExecutingEvent">
<BeginStoryboard Storyboard="{StaticResource executingStateAnimation}"/>
<BeginStoryboard Name="rotateAnimation"
Storyboard="{StaticResource rotateAnimation}"/>
</EventTrigger>
This starts the Executing State animation which converts the color to Green. Then it starts the rotating event which starts rotating the ring. Let's take the Success State event:
<EventTrigger RoutedEvent="local:QueryStatus.SuccessEvent">
<StopStoryboard BeginStoryboardName="rotateAnimation"/>
<BeginStoryboard Storyboard="{StaticResource successStateAnimation}"/>
</EventTrigger>
This (and all other state events) will stop the rotation first and changes the color to Green (denoting a success).
Code Behind
It exposes some public
methods that can be used by any client using this. These public
methods will fire the appropriate event. I have attached a Synchronous and an Asynchronous version of the client to demonstrate using the control in both modes. Note that Usage of control will not change in asynchronous mode. It is only the client that is coded differently. In case the code does not compile (as you might not have .NET SP1, simply fix the AsynchronouosWindow.xaml client code or else exclude it from project). I have attached the sample code and it's too simple to use the Progress Bar Control. Just add the namespace and then include it. If you set the height = width
, then it will be a perfect round rotating circle, else it will be a rotating ellipse. Enjoy!
History
- 26th October, 2009: Initial post