How to create Busy Indicator like Window 7 with Spinner Animation in WPF

No.of Views3125
Bookmarked0 times
Downloads 
Votes0
By  Prabu   On  13 Dec 2010 09:12:32
Tag : WPF , Custom Controls
In this article I will show how to create loading or busy indicator control like windows 7 or Windows Vista using Spinner Animation in Windows Presentation Foundation (WPF).
emailbookmarkadd commentsprint

Images in this article missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at info@codegain.com

 

Introduction

In this article I will show how to create loading or busy indicator control like windows 7 or Windows Vista using Spinner Animation in Windows Presentation Foundation (WPF).I have been working on WPF XBAP projects which establish the connection between mobile and system similar to Remote Desktop connectivity. I am in need to show the current status and waiting status between mobile and system connection. Hence I've created this control which is showing similar to Win7/Vista busy indicator. I am happy to share the control with you.

Implementation

Initially I have a tried to show the circle shaped rectangular using rotate animation.  But I couldn't get the expected feel similar to Win7/Vista like busy indicator. Then I have spent few minutes in net and I come to know about the spinner animation and found the ImageStrip control from this link for implementing Image animation.  Then I have created Win7/Vista like busy indicator using the following code and control template.

ImageStrip.cs

1     public class ImageStrip : Control
 2     {
 3         #region Dependency Properties
 4 
 5         public int Frame
 6         {
 7             get { return (int)GetValue(FrameProperty); }
 8             set { SetValue(FrameProperty, value); }
 9         }
10 
11         public static readonly DependencyProperty FrameProperty =
12             DependencyProperty.Register("Frame", typeof(int), typeof(ImageStrip), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.AffectsRender));
13 
14         public double FrameSize
15         {
16             get { return (double)GetValue(FrameSizeProperty); }
17             set { SetValue(FrameSizeProperty, value); }
18         }
19 
20         public static readonly DependencyProperty FrameSizeProperty =
21             DependencyProperty.Register("FrameSize", typeof(double), typeof(ImageStrip), new FrameworkPropertyMetadata(0D, FrameworkPropertyMetadataOptions.AffectsRender));
22 
23         public ImageSource Image
24         {
25             get { return (ImageSource)GetValue(ImageProperty); }
26             set { SetValue(ImageProperty, value); }
27         }
28 
29         public static readonly DependencyProperty ImageProperty =
30             DependencyProperty.Register("Image", typeof(ImageSource), typeof(ImageStrip), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));
31 
32         public Orientation Orientation
33         {
34             get { return (Orientation)GetValue(OrientationProperty); }
35             set { SetValue(OrientationProperty, value); }
36         }
37 
38         public static readonly DependencyProperty OrientationProperty =
39             DependencyProperty.Register("Orientation", typeof(Orientation), typeof(ImageStrip), new FrameworkPropertyMetadata(Orientation.Horizontal, FrameworkPropertyMetadataOptions.AffectsRender));
40 
41         #endregion
42 
43         #region Rendering
44 
45         protected override void OnRender(DrawingContext drawingContext)
46         {
47             if (Image != null)
48             {
49                 Rect rect = new Rect(0, 0, RenderSize.Width, RenderSize.Height);
50 
51                 ImageBrush brush = new ImageBrush(Image);
52                 brush.Stretch = Stretch.None;
53                 brush.Viewbox = (Orientation == Orientation.Vertical) ?
54                     new Rect(0, (((Frame + 0.5) * FrameSize) / Image.Height) - 0.5, 1, 1) :
55                     new Rect((((Frame + 0.5) * FrameSize) / Image.Width) - 0.5, 0, 1, 1);
56 
57                 drawingContext.DrawRectangle(brush, null, rect);
58             }
59         }
60 
61         #endregion
62     }
63

 

BusyIndicator.cs

1     public class BusyIndicator : Control
 2     {
 3         static BusyIndicator()
 4         {
 5             DefaultStyleKeyProperty.OverrideMetadata(typeof(BusyIndicator), new FrameworkPropertyMetadata(typeof(BusyIndicator)));
 6         }
 7 
 8         public string Text
 9         {
10             get { return (string)GetValue(TextProperty); }
11             set { SetValue(TextProperty, value); }
12         }
13         public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(BusyIndicator), new UIPropertyMetadata(null));
14     }
15

 

XAML Style

1 <ResourceDictionary 
 2     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4     xmlns:local="clr-namespace:SpinnerAnimation">
 5     
 6     <Style x:Key="{x:Type local:BusyIndicator}" TargetType="{x:Type local:BusyIndicator}">
 7         <Setter Property="HorizontalAlignment" Value="Center" />
 8         <Setter Property="VerticalAlignment" Value="Center" />
 9         <Setter Property="Template" >
10             <Setter.Value>
11                 <ControlTemplate TargetType="{x:Type local:BusyIndicator}">
12                     <Border x:Name="mainBorder" Background="#FFFFFFFF" CornerRadius="3">
13                         <Grid>
14                             <Border x:Name="shaddowBorder" Background="#FFFFFFFF" CornerRadius="3" BorderBrush="#0D566B" BorderThickness="1">
15                                 <Border.Effect>
16                                     <DropShadowEffect  BlurRadius="2" ShadowDepth="3" Opacity="0.6" Color="#FF000000" Direction="310"/>
17                                 </Border.Effect>
18                             </Border>
19                             <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
20                                 <Viewbox Height="24" Width="24" Margin="2">
21                                     <local:ImageStrip Image="Images\BusyIndicator.png" FrameSize="20" Width="20" Height="20" Margin="0 3 0 0">
22                                         <local:ImageStrip.Effect>
23                                             <DropShadowEffect BlurRadius="3" ShadowDepth="3" Opacity="0.6" Color="#FF000000" Direction="300"/>
24                                         </local:ImageStrip.Effect>
25                                         <FrameworkElement.Triggers>
26                                             <EventTrigger RoutedEvent="FrameworkElement.Loaded">
27                                                 <BeginStoryboard>
28                                                     <Storyboard>
29                                                         <Int32Animation From="0" To="17" Duration="0:0:0.75" Storyboard.TargetProperty="Frame" RepeatBehavior="Forever" />
30                                                     </Storyboard>
31                                                 </BeginStoryboard>
32                                             </EventTrigger>
33                                         </FrameworkElement.Triggers>
34                                     </local:ImageStrip>
35                                 </Viewbox>
36                                 <Label x:Name="label" FontFamily="Calibri" Content="{TemplateBinding Text}" FontSize="12" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center" />
37                             </StackPanel>
38                         </Grid>
39                     </Border>
40                     <ControlTemplate.Triggers>
41                         <Trigger Property="Text" Value="{x:Null}">
42                             <Setter Property="Visibility" Value="Collapsed" TargetName="label" />
43                             <Setter Property="Visibility" Value="Collapsed" TargetName="shaddowBorder" />
44                         </Trigger>
45                     </ControlTemplate.Triggers>
46                 </ControlTemplate>
47             </Setter.Value>
48         </Setter>
49     </Style>
50     
51 </ResourceDictionary>

 

By using ImageStrip control, we can also show the downloading, ready to connect, etc., indicators. We just need to create an appropriate image and give the Frame, FrameSize, Image and Orientation (If it is required). The sample code is below,

Example:

1     <local:ImageStrip Image="Images/Download.png" FrameSize="22.27" Width="22" Height="22" Margin="10" Grid.Row="2" Grid.Column="3">
 2         <FrameworkElement.Triggers>
 3             <EventTrigger RoutedEvent="FrameworkElement.Loaded">
 4                 <BeginStoryboard>
 5                     <Storyboard>
 6                         <Int32Animation From="0" To="6" Duration="0:0:1.5" Storyboard.TargetProperty="Frame" RepeatBehavior="Forever" />
 7                     </Storyboard>
 8                 </BeginStoryboard>
 9             </EventTrigger>
10         </FrameworkElement.Triggers>
11     </local:ImageStrip>
12 
13     <local:ImageStrip Image="Images/Ready.png" FrameSize="21" Width="21" Height="21" Grid.Row="3" Grid.Column="2">
14         <FrameworkElement.Triggers>
15             <EventTrigger RoutedEvent="FrameworkElement.Loaded">
16                 <BeginStoryboard>
17                     <Storyboard>
18                         <Int32Animation From="0" To="5" Duration="0:0:1.3" Storyboard.TargetProperty="Frame" RepeatBehavior="Forever" />
19                     </Storyboard>
20                 </BeginStoryboard>
21             </EventTrigger>
22         </FrameworkElement.Triggers>
23     </local:ImageStrip>
24

 

Output 

Image Loading

Download Sample Project

Download source files -35 kb

Conclusion

In this article you have learned show how to create loading or busy indicator control like windows 7 or Windows Vista using Spinner Animation in Windows Presentation Foundation (WPF).thank you for reading.

 
Sign Up to vote for this article
 
About Author
 
Prabu
Occupation-Software Engineer
Company-
Member Type-Fresh
Location-India
Joined date-23 Jun 2010
Home Page-
Blog Page-http://prabu-guru.blogspot.com/
 
 
Other popularSectionarticles
Comments
There is no comments for this articles.
Leave a Reply
Title:
Display Name:
Email:
(not display in page for the security purphase)
Website:
Message:
Please refresh your screen using Ctrl+F5
If you can't read this number refresh your screen
Please input the anti-spam code that you can read in the image.
^ Scroll to Top