Display a progress bar with text in WPF and C#

[progress bar]

As is so often the case in WPF, the solution is simple after you spend a few hours figuring out what controls to use. This example uses a normal Grid control that holds a StackPanel. The following code shows the controls inside the StackPanel.

<Button Name="goButton" Width="75" Height="30"
    Content="Go" Click="goButton_Click"/>

<Border Name="progBorder"
    Margin="0,10,0,0" Width="300" Height="25"
    BorderBrush="Black" BorderThickness="1">
    <Grid Margin="0">
        <Label Name="progBgLabel" Width="0" 
            HorizontalAlignment="Left"
            Background="LightGreen" />
        <Label Name="progLabel"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Content="0%" />
    </Grid>
</Border>

The button is there to let you start the progress simulation.

After the button comes a Border. This displays the black border around the progress bar and acts as a container for the remaining controls. This is the control that you should use to change the size or position of the progress bar. For example, this program makes the progress bar 300 pixels wide, 25 pixels tall, and centered inside the StackPanel. You can modify the Border control to change those values.

The progress bar must hold two Label controls, one to display the colored background and one to display text. Because a Border control can have only one child, the XAML code places a Grid inside the Border and then places the two Label controls inside the Grid.

Initially the controls are set to show no green background and the string “0%.”

The program uses the following code behind to prepare to update the progress.

// The timer.
private DispatcherTimer Timer = null;

// Progress parameters.
private const double ProgressMinimum = 0;
private const double ProgressMaximum = 100;
private const double ProgressStep = 4;
private double ProgressValue = ProgressMinimum;

WPF doesn’t have a Timer control, so the code declares a DispatcherTimer to use instead.

The code then defines some values to use while updating the progress. The ProgressValue variable shows the current progress.

When the window loads, the following code executes.

// Create the timer.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
    Timer = new DispatcherTimer();
    Timer.Tick += new EventHandler(Timer_Tick);
    Timer.Interval = new TimeSpan(0, 0, 0, 0, 100);
}

This code creates the DispatcherTimer, assigns its Tick event handler, and sets its interval to 100 milliseconds.

When you click the Go button, the following code executes.

// Start a timer.
private void goButton_Click(object sender, RoutedEventArgs e)
{
ProgressValue = ProgressMinimum;
Timer.Start();
}

This code sets ProgressValue to the minimum and enables the timer. The following event handler executes when the timer fires.

// Simulate a task's progress.
private void Timer_Tick(object sender, EventArgs e)
{
    ProgressValue += ProgressStep;
    if (ProgressValue > ProgressMaximum)
    {
        ProgressValue = ProgressMinimum;
        Timer.Stop();
    }

    // Show the progress.
    double fraction = (ProgressValue - ProgressMinimum) /
        (ProgressMaximum - ProgressMinimum);
    progBgLabel.Width = progBorder.Width * fraction;

    progLabel.Content = ProgressValue.ToString() + "%";
}

This code adds ProgressStep to ProgressValue. Then if ProgressValue is greater than ProgressMaximum, the code resets ProgessValue to ProgressMinimum and stops the timer.

After it updates ProgressValue, the code calculates the fraction of the Border control’s width that should filled with background. It multiplies that fraction by the Border control’s width and sets the background label’s width to the result.

The code finishes by setting the progLabel control’s contents to the ProgressValue. Note that this string is displayed with no digits after the decimal as long as ProgressValue has an integer value, as it does in this example.

There are several modifications that you could make to this example. For instance, you could left justify the text label. You could also fill the background label with a color gradient or tiled picture.

If you need to do something like this often, then you might want to make a custom control to fill the background and display the numeric value more easily.


Download Example   Follow me on Twitter   RSS feed   Donate




About RodStephens

Rod Stephens is a software consultant and author who has written more than 30 books and 250 magazine articles covering C#, Visual Basic, Visual Basic for Applications, Delphi, and Java.
This entry was posted in controls, user interface, wpf, XAML and tagged , , , , , , , , , , , , , . Bookmark the permalink.

One Response to Display a progress bar with text in WPF and C#

  1. Hi Rod,

    Thank you, for this post, very clear explanation. I will have a play round with this one, as I can already see some uses for this in some current projects, and it should work quite well in Xamarin as well.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.