Blog Archives

WPF: How to Create a Reversing ProgressBar

 

 

In some of my earlier blogs – here, here and here, I looked at some rather colorful, non-rectangular versions of the ProgressBar. Although you probably wouldn't want to use some of those versions outside of a game environment, I hope it did show you how you can create and tweak non-rectangular versions. In this blog, I want to examine a less bizarre variation and along the way hopefully show you some more useful WPF basics.

Reversing the Default ProgressBar
The default ProgressBar is rectangular, has slightly rounded corners, a Gray Background, Linear Gradient Green Foreground and, most importantly, it traverses from left to right. I was wondering about how to change this and have a ProgressBar that traversed from right to left – a kind of a countdown effect instead of the usual fill-increasing effect. Because I was in ControlTemplate mode, I confess that I initially overlooked the obvious solution – total simplicity in WPF – and created a whole new template that did the job. I'll show you the obvious WPF solution shortly, but first let's just look at how this can be done as a ControlTemplate task.

ControlTemplate
I set about this by using a combination of Expression Blend and Visual Studio. I know I could have done it all in Blend using the Edit Template tools, but I came up this WPF route the hard way, from back in the early days when there were no tools and you had to become a XAML-head to get anywhere with this new-fangled thing called WPF. So I find that I still prefer to create my ControlTemplates in XAML in Visual Studio and use Blend when I want to do anything fancy with graphics or animation.

If you find it easier to do it all in Blend, I have no problem with that, but here's my way. First create a ControlTemplate, Key it as 'ReverseBasicPB' and set its TargetType to ProgressBar. The visual elements of the template will all be held inside a Grid. 

    <ControlTemplate x:Key="ReverseBasicPB" TargetType="{x:Type ProgressBar}">

      <Grid>

 

      </Grid>

    </ControlTemplate> 

As you will know from the earlier blogs, the ProgressBar requires two named parts – PART_Track and PART_Indicator. In this version, PART_Track will consist of a Rectangle inside a Border and PART_Indicator will be a Rectangle with a reasonable copy of the Green Linear Brush.
(As a side note, it is possible to dig into the WPF namespaces and get hold of the ProgressBarGlassyHighlight and ProgressBarTopHighlight Brushes, but I was content to go with my approximation.)

Here is the markup for the PART_Track: 

       <Border Name="PART_Track" BorderBrush="DarkGray"

               BorderThickness="2" CornerRadius="3" >

          <Rectangle Fill="LightGray"

               RadiusX="3" RadiusY="3"/>

        </Border> 

Note that to achieve the rounded corner effect, Border uses CornerRadius and Rectangle uses RadiusX and RadiusY.

The markup for the Indicator is just as simple: 

          <Rectangle Name="PART_Indicator" HorizontalAlignment="Right"

                    RadiusX="3" RadiusY="3" 

                    Margin="2,2,2,2">

          <Rectangle.Fill>

            <LinearGradientBrush EndPoint="0.5,0" StartPoint="0.5,1">

              <GradientStop Color="#FF5FBB23" Offset="0.525"/>

              <GradientStop Color="White"/>

              <GradientStop Color="#FF63BC28"/>

              <GradientStop Color="#FF95EDA5" Offset="0.542"/>

            </LinearGradientBrush>

          </Rectangle.Fill>

        </Rectangle> 

The key property here is the HorizontalAlignment. By setting it to Right we ensure that the ProgressBar Indicator will start at the right hand side and stretch out towards the left.

Demo
The following markup in a Window will create two ProgressBars, one default style and the other using this ControlTemplate: 

    <Grid>

    <Grid.RowDefinitions>

      <RowDefinition Height="87*" />

      <RowDefinition Height="175*" />

    </Grid.RowDefinitions>

 

    <ProgressBar x:Name="PBDefault" Width="150" Height="33">

 

    </ProgressBar>

    <ProgressBar Name="MyPB" Width="150" Height="33"

          Template="{StaticResource ReverseBasicPB}" Margin="22"

          Grid.Row="1"

          VerticalAlignment="Top" />

  </Grid> 

Add in the animation code-behind used in previous examples: 

    Private Sub ReverseBasic_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

        Dim a As New DoubleAnimation

        a.From = 0

        a.To = 100

        a.Duration = New TimeSpan(0, 0, 6)

 

        MyPB.BeginAnimation(ProgressBar.ValueProperty, a)

 

        a.From = 0

        a.To = 100

        a.Duration = New Duration(TimeSpan.Parse("0:0:6"))

 

        PBDefault.BeginAnimation(ProgressBar.ValueProperty, a)

    End Sub 

When you run this, completed ProgressBars are reasonably close in looks, the only major difference being that the templated one at the bottom runs right to left.

 

Although the creation of the ControlTemplate was only a few minutes work and opens the way for further visual changes (which I'll probably blog about later), if you just want the default ProgressBar reversed, the simple way is as follows:

Add a new ProgressBar to the Window, but this time include a LayoutTransform to rotate it 180 degrees. 

    <ProgressBar x:Name="PBDefaultReversed"

                 Width="150" Height="33"

                 Grid.Row="2" >

      <ProgressBar.LayoutTransform>

        <RotateTransform Angle="180" />

      </ProgressBar.LayoutTransform>

    </ProgressBar> 

(You'll also need to add the extra row to the Grid if you are following along and creating this sample yourself:) 

    <Grid.RowDefinitions>

      <RowDefinition Height="87*" />

      <RowDefinition Height="85*" />

      <RowDefinition Height="90*" />

    </Grid.RowDefinitions> 

And don't forget to animate it in the code-behind.

The final result, with the default ProgressBar at the top, the templated one in the middle and the transformed one at the bottom, looks like this:

I chose not to use a gradient for the background Gray, but of course you can implement this if you prefer.

WP Like Button Plugin by Free WordPress Templates