Click here to Skip to main content
Click here to Skip to main content

WPF: Round Progress Bar

By , 12 Jul 2009
Rate this:
Please Sign up or sign in to vote.

Introduction

The standard WPF progress bar is very boring, and doesn't allows lot of customizations. I created a round progress bar like the ones that I always see in the web and in Flash applications.

Here is the simple idea of how to implement such a control. I used two Canvases, a TextBox and 12 Rectangles to create the progress bar.

Here is the XAML code of the UserControl:

<UserControl x:Class="RounderProgressBar.RounderProgressBarControl"  
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml 
    Height="400" Width="400">

    <UserControl.Resources>  
        <Style x:Key="canvasStyle" TargetType="{x:Type Canvas}"> 
            <Setter Property="Background" Value="Transparent"/> 
        </Style>  
        <Style x:Key ="rectangle" 
                     TargetType="{x:Type Rectangle}"> 
            <Setter Property="Width" Value="35"/> 
            <Setter Property="Height" Value="100"/> 
            <Setter Property="Fill" Value="LightBlue"/> 
            <Setter Property="Canvas.Left" Value="190"/> 
            <Setter Property="Canvas.Top" Value="0"/> 
            <Setter Property="RadiusX" Value="10"/> 
            <Setter Property="RadiusY" Value="10"/> 
        </Style> 
        <Style x:Key="percents" TargetType="{x:Type TextBox}">
            <Setter Property="FontSize" Value="20" />
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
            <Setter Property="IsReadOnly" Value="true"/>
        </Style>      
    </UserControl.Resources> 

    <Canvas RenderTransformOrigin="0.5,0.5" 
             Style="{StaticResource canvasStyle}"> 
        <TextBox Name="tbPercents" 
          Style="{StaticResource percents}"  
          Canvas.Left="172" Canvas.Top="189" 
          TextChanged="tblPercents_TextChanged"> 
            100% 
        </TextBox>         
        <Canvas Name="rotationCanvas" 
               RenderTransformOrigin="0.5,0.5" 
               Style="{StaticResource canvasStyle}"> 
            <Rectangle  Style="{StaticResource rectangle}"> 
            </Rectangle> 
            <Rectangle Opacity="0.92" 
                    Style="{StaticResource rectangle}"> 
                <Rectangle.RenderTransform> 
                    <RotateTransform Angle="30" 
                            CenterX="10" CenterY="200"/> 
                </Rectangle.RenderTransform> 
            </Rectangle> 
            <Rectangle Opacity="0.84" 
                    Style="{StaticResource rectangle}"> 
                <Rectangle.RenderTransform> 
                    <RotateTransform Angle="60" 
                           CenterX="10" CenterY="200"/> 
                </Rectangle.RenderTransform> 
            </Rectangle> 
            <Rectangle Opacity="0.76" 
                     Style="{StaticResource rectangle}" > 
                <Rectangle.RenderTransform> 
                    <RotateTransform Angle="90" 
                          CenterX="10" CenterY="200"/> 
                </Rectangle.RenderTransform> 
            </Rectangle> 
            <Rectangle Opacity="0.66" 
                   Style="{StaticResource rectangle}"> 
                <Rectangle.RenderTransform> 
                    <RotateTransform Angle="120" 
                         CenterX="10" CenterY="200"/> 
                </Rectangle.RenderTransform> 
            </Rectangle> 
            <Rectangle Opacity="0.58" 
                      Style="{StaticResource rectangle}" > 
                <Rectangle.RenderTransform> 
                    <RotateTransform Angle="150" 
                           CenterX="10" CenterY="200"/> 
                </Rectangle.RenderTransform> 
            </Rectangle> 
            <Rectangle Opacity="0.5" 
                      Style="{StaticResource rectangle}" > 
                <Rectangle.RenderTransform> 
                    <RotateTransform Angle="180" 
                          CenterX="10" CenterY="200"/> 
                </Rectangle.RenderTransform> 
            </Rectangle> 
            <Rectangle Opacity="0.42" 
                    Style="{StaticResource rectangle}" > 
                <Rectangle.RenderTransform> 
                    <RotateTransform Angle="210" 
                      CenterX="10" CenterY="200"/> 
                </Rectangle.RenderTransform> 
            </Rectangle> 
            <Rectangle Opacity="0.34" 
                      Style="{StaticResource rectangle}" > 
                <Rectangle.RenderTransform> 
                    <RotateTransform Angle="240" 
                      CenterX="10" CenterY="200"/> 
                </Rectangle.RenderTransform> 
            </Rectangle> 
            <Rectangle Opacity="0.26" 
                  Style="{StaticResource rectangle}" > 
                <Rectangle.RenderTransform> 
                    <RotateTransform Angle="270" 
                      CenterX="10" CenterY="200"/> 
                </Rectangle.RenderTransform> 
            </Rectangle> 
            <Rectangle Opacity="0.16" 
                 Style="{StaticResource rectangle}" > 
                <Rectangle.RenderTransform> 
                    <RotateTransform Angle="300" 
                      CenterX="10" CenterY="200"/> 
                </Rectangle.RenderTransform> 
            </Rectangle> 
            <Rectangle Opacity="0.08" 
                   Style="{StaticResource rectangle}" > 
                <Rectangle.RenderTransform> 
                    <RotateTransform Angle="330" 
                       CenterX="10" CenterY="200"/> 
                </Rectangle.RenderTransform> 
            </Rectangle> 
            <Canvas.RenderTransform> 
                <RotateTransform x:Name="SpinnerRotate"  
                   Angle="0" CenterX="200" 
                   CenterY="200" /> 
            </Canvas.RenderTransform> 
        </Canvas> 
    </Canvas> 
</UserControl>

To add some animation to the progress bar, I use a System.Timer and rotate the second Canvas on 30 angles every 100 milliseconds.

Here is the code in С#:

using System.Timers; 
using System.Windows; 
using System.Windows.Controls;

namespace RounderProgressBar 
{ 
    /// <summary> 
    /// Interaction logic for RounderProgressBar.xaml 
    /// </summary> 
    public partial class RounderProgressBarControl : UserControl 
    { 
        private const string PERCENTS_TEXT = "{0}%"; 
        private delegate void VoidDelegete(); 
        private Timer timer; 
        private bool loaded; 
        private int progress; 

        public RounderProgressBarControl() 
        { 
            InitializeComponent(); 
            Loaded += OnLoaded; 
        }

        void OnLoaded(object sender, RoutedEventArgs e) 
        { 
            timer = new Timer(100); 
            timer.Elapsed += OnTimerElapsed; 
            timer.Start(); 
            loaded = true; 
        }

        void OnTimerElapsed(object sender, ElapsedEventArgs e) 
        { 
            rotationCanvas.Dispatcher.Invoke 
            ( 
                new VoidDelegete( 
                    delegate 
                        { 
                            SpinnerRotate.Angle += 30; 
                            if (SpinnerRotate.Angle == 360) 
                            { 
                                SpinnerRotate.Angle = 0; 
                            } 
                        } 
                    ), 
                null 
            );  
        }

        private void tblPercents_TextChanged(object sender, 
                     TextChangedEventArgs e) 
        { 
            if (loaded) 
            { 
                Canvas.SetLeft(tbPercents, 
                  (rotationCanvas.ActualHeight - tbPercents.ActualWidth) / 2); 
                Canvas.SetTop(tbPercents, 
                  (rotationCanvas.ActualHeight - tbPercents.ActualHeight) / 2);    
            } 
        } 

        private void UpdateProgress() 
        { 
            tbPercents.Text = string.Format(PERCENTS_TEXT, progress); 
        } 

        public int Progress 
        { 
            get { return progress; } 
            set 
            { 
                progress = value; 
                UpdateProgress(); 
            } 
        } 
    } 
}

You can easily change the percentage info on the progress bar using the Progress property.

public int Progress 
{  
    get { return progress; } 

    set 
    { 
        progress = value; 
        UpdateProgress(); 
    }  
}

License

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

About the Author

NeoPunk

Belarus Belarus
No Biography provided

Comments and Discussions

 
QuestionIts not working with asynchronous call [modified] PinmemberMember 34620802-Mar-12 20:21 
QuestionProgress not work! PinmemberAli_MH22-May-11 20:36 
Generalweird progress bar shows up as top CPU drain on ANTS Profiler Pinmemberdevvvy6-Mar-11 8:43 
GeneralRe: weird progress bar shows up as top CPU drain on ANTS Profiler PinmemberNeoPunk6-Mar-11 11:24 
GeneralMy vote of 5 Pinmemberkkirusha21-Nov-10 11:36 
GeneralA good start... PinmemberJosh Fischer11-Aug-09 7:53 
GeneralRe: A good start... PinmemberKirill Kovalev14-Aug-09 19:22 
QuestionResize? PinmemberDaProgramma25-Jul-09 2:40 
AnswerRe: Resize? PinmemberKirill Kovalev25-Jul-09 23:17 
QuestionArchive Size Pinmembersotona12-Jul-09 4:16 
AnswerRe: Archive Size PinmemberKirill Kovalev12-Jul-09 6:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

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

| Advertise | Privacy | Mobile
Web03 | 2.8.140415.2 | Last Updated 12 Jul 2009
Article Copyright 2009 by NeoPunk
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid