Programming the Task Bar in Windows 7 with WPF 4, Part Four – Progress
By Alessandro Del Sole – Microsoft MVP
Read the entire series of articles here: Programming the Windows 7 Task Bar with WPF 4
Showing the progress of a task is important in every application’s UI. This gives users the right perception of
the amount of time required for completing a particular operation. For example, when you download a file
from the Internet, whichever Web browser you use the browser itself shows a dialog that displays the
download percentage and the remaining time. In most .NET applications the UI element used for showing
the progress of a task is the ProgressBar control and this is true for WPF as well. The only limitation is that
you need to open the application’s active window in order to check the task progress. Fortunately Windows
7 introduces another improvement, known as Progress Bar Icons; such a feature allows utilizing the
application’s icon on the task bar like a fully functional progress bar so that users can see progress without
activating the application. Moreover progress bar icons can show faults in the task progress. Figure 1 shows
an example related to an instance of Internet Explorer while downloading a file from the Internet.
Figure 1 – The Internet Explorer’s progress bar icon
In this article I will describe how to easily implement progress bar icons in WPF 4 applications with Visual
Creating the sample project
In real world applications there are so many different situations in which you need to show the progress of
a task. Because of this, the code for the sample application will just show the progress of time passing. The
example will focus on how you enable progress bar icons and how you change the appearance of such icons
according to the progress state. The application will show some progress within a ProgressBar control
exposed by the main Window and on the application’s icon. The first step is to create a new WPF project
with Visual Basic 2010 (or Visual C#4.0). Once the IDE’s designer is ready, we can write the simple user
Defining the User Interface in XAML
Just like the previous articles of the series, in order to interact with Windows 7’s task bar you need a
TaskbarItemInfo object. Also, for this particular example the application requires a ProgressBar control.
Listing 1 shows the XAML code for the sample application.
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Window.TaskbarItemInfo> <TaskbarItemInfo/> </Window.TaskbarItemInfo> <Grid> <ProgressBar Name="ProgressBar1" Height="40" Margin="5"/> </Grid> </Window>
Listing 1 – Defining the user interface
Most of the work is made on the code-behind side, so you need to open the MainWindow.xaml.vb code
Understanding Progress States
You specify icons as progress bar icons by assigning the TaskbarItemInfo.ProgressState property with one of
the values exposed by the System.Windows.Shell.TaskbarItemProgressState enumeration. Available values
are the following:
- Normal: progress bar icon is green and enabled for showing progress
- Error: progress bar icon gets colored in red and is used for communicating faults while progressing
- Paused: progress bar icon gets colored in yellow and is used when the progress is paused
- Indeterminate: progress bar icon is again colored in green and display progress intermittently; it is
used for communicating an idle state or that an input from the user is requested
There is also a None value which is the default value, but generally you use Normal. Let’s begin by
implementing a normal state progress. Later in the article I will describe the other states.
Displaying progress on the icon
The sample code basically wastes some time in an asynchronous way, sending the progress percentage to
both the ProgressBar on the Window and the progress bar icon. To accomplish this, we can use a
BackgroundWorker control which is useful for asynchronous operations and for multithreading in WPF. The
progress of such a control will be sent to progress bars. If you are not familiar with the BackgroundWorker
control, you can check out the MSDN documentation for this control. Code in Listing 2 demonstrates how
to reach the proposed objective.
Imports System.ComponentModel Class MainWindow Dim WithEvents worker As BackgroundWorker Private Sub Window_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded Me.worker = New BackgroundWorker 'Enable progress reporting worker.WorkerReportsProgress = True 'Set the progress state as "normal" TaskbarItemInfo.ProgressState = Shell.TaskbarItemProgressState.Normal 'Start the work worker.RunWorkerAsync() End Sub Private Sub worker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles worker.DoWork 'Wasting some time asynchronously For i As Integer = 0 To 99 Step 10 System.Threading.Thread.Sleep(1000) 'Raises the ProgressChanged event passing the value CType(sender, System.ComponentModel.BackgroundWorker).ReportProgress(i) Next i End Sub 'Increment the value on both progress bars Private Sub worker_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles worker.ProgressChanged ProgressBar1.Value = e.ProgressPercentage TaskbarItemInfo.ProgressValue = CDbl(e.ProgressPercentage) / 100 End Sub 'Work completed, maximum value is set Private Sub worker_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles worker.RunWorkerCompleted ProgressBar1.Value = 100 TaskbarItemInfo.ProgressValue = 1.0 End Sub End Class
Listing 2 – Enabling progress bar icons and displaying progress
The above code presents two points of interest. The first one is the following line of code:
'Set the progress state as "normal" TaskbarItemInfo.ProgressState = Shell.TaskbarItemProgressState.Normal
The code tells the task bar that the progress bar icon will show the progress in a normal state, thus green.
The second point of interest is about the assignment of the TaskbarItemInfo.ProgressValue property like
TaskbarItemInfo.ProgressValue = CDbl(e.ProgressPercentage) / 100 ... TaskbarItemInfo.ProgressValue = 1.0
This means that you display the progress by assigning the above mentioned property with a value of type
Double. If you now run the application, you will get a result as shown in Figure 2.
Figure 2 – The sample application shows progress on the application’s icon
This is the case of a normal progress state. There are situations in which you need to show an error in
progress or simply capture the user attention with a different progress state. Let’s see how we can do that
Imagine your application reaches an idle state or that you need to request an action from the user while
the progress is running or your application encounters a temporary problem. In such situations it can be
useful to communicate to the user that the operation in progress is temporarily unavailable. To accomplish
this, the System.Windows.Shell.TaskbarItemProgressState enumeration provides the Indeterminate value
which makes the progress bar icon run intermittently. To provide an example, replace the
worker_RunWorkerCompleted event handler with the one shown in Listing 3.
'Work completed, maximum value is set Private Sub worker_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles worker.RunWorkerCompleted ProgressBar1.Value = 100 TaskbarItemInfo.ProgressValue = 1.0 TaskbarItemInfo.ProgressState = Shell.TaskbarItemProgressState.Indeterminate Dim result = MessageBox.Show("The progress completed. Would you like to exit now?", "", MessageBoxButton.YesNo) If result = MessageBoxResult.Yes Then Application.Current.Shutdown() End Sub
Listing 3 – Showing an indeterminate progress state
In this case the application is requesting an action from the user once the progress completes, putting the
progress bar icon on the Indeterminate state. Figure 3 shows an example.
Figure 3 – Showing an indeterminate progress state
You can take advantage of progress bar icons for displaying errors too, as demonstrated in next section.
Paused and Error states
You can take advantage of the progress bar icon for displaying an error or paused state. This is
accomplished by assigning the TaskbarItemInfo.ProgressState property with either the
TaskbarItemProgressState.Error or TaskbarItemProgressState.Paused values. Code in Listing 4
demonstrates how to handle both scenarios by rewriting the worker_RunWorkerCompleted event handler.
'Work completed, maximum value is set Private Sub worker_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles worker.RunWorkerCompleted If e.Cancelled = True Then Me.TaskbarItemInfo.ProgressState = Shell.TaskbarItemProgressState.Paused ElseIf e.Error IsNot Nothing Then Me.TaskbarItemInfo.ProgressState = Shell.TaskbarItemProgressState.Error Else ProgressBar1.Value = 100 TaskbarItemInfo.ProgressValue = 1.0 End If End Sub
Listing 4 – Handling Paused and Error states
It is worth mentioning that in the sample application you need to invoke the worker.CancelAsync method
in order to make the e variable value change to Cancelled. Figure 4 shows how the progress bar icon
appears in the error state.
Figure 4 – the Error state
In the case of the Paused state, the progress bar icon gets colored in yellow.
Progress bar icons are a great improvement in Windows 7 providing a very useful way for giving users the
perception of how the application is progressing without having to open the application window. WPF 4
makes it easy to program this feature as well as many other new features in Windows 7.
About the author
Alessandro Del Sole is a Microsoft Visual Basic MVP and Team Member in the Italian “Visual Basic Tips &
Tricks” Community. He writes many Italian and English language community articles and books about .NET
development and is the author of the book “Visual Basic 2010 Unleashed”. He also enjoys writing freeware
and open-source developer tools. You can visit Alessandro’s Italian language blog or his English language blog.