Mobile Zone is brought to you in partnership with:

I love technology. Plain and simple. You can generally find me writing software, figuring out how to get rid of cable, playing on my Xbox, or traveling around this country speaking about software development. If you're doing something cool with technology, let me know. I'd love to hear your story about something amazing. You can find my blog at jeffblankenburg.com Jeff is a DZone MVB and is not an employee of DZone and has posted 71 posts at DZone. You can read more from them at their website. View Full User Profile

31 Days of Mango | Day #15: The Progress Bar

11.15.2011
| 3140 views |
  • submit to reddit

This article is Day #15 in a series called 31 Days of Mango, and was written by guest author Doug Mair.  Doug can be reached on Twitter at @doug_mair or at doug.mair@gmail.com.

Day15-ProgressBar

Any time you have a operation that will take more than a couple of seconds to complete, it’s a good idea to let your users know that your application is still making progress and is not just stuck in a loop forever.

How should you let your user know what’s happening? Well you can show them a text message with actual numbers of bytes downloaded or seconds left for an operation. But often the user is not concerned with that level of detail. Progress Bars are a great way to show your users that an operation is making progress, without overloading them with too many details. A progress bar can show this information in two different ways: indeterminate and indeterminate mode.

Indeterminate Mode

Indeterminate mode is when you cannot determine how long the operation will take to complete. For example if you are connecting to a server, you do not know when or if the operation will complete. Indeterminate mode Progress Bars show their status by having dots move from left to right in an animation. This is great for showing that something is happening, but it doesn’t give the user an indication of the amount of progress. To make a progress bar show the indeterminate mode, check the IsIndeterminate checkbox of the progress bar.

image_thumb5

Determinate Mode

If you can determine approximately how long an operation takes to complete, use the Determinate mode to let the user know the percentage that is left in the operation. For example, if you are downloading a file, you know the total file size, and as the download continues, you get updates that tell you the number of bytes downloaded so far.

You can then divide the Total File Size by the Current Bytes Downloaded to get the percentage completion. This code shows an example of how this could be done.

progressBar1.Value = (float)bytesRead / TotalFileSize;

If you want to show your user the percent of progress an operation is taking, you display that information in a Progress Bar. To show the Determinate mode, uncheck the IsIndeterminate checkbox and set the value to correlate to the percentage completion.

image_thumb4

With Windows Phone 7.5 Mango, you have 2 choices for Progress Bars:

1) Progress Bar – A control that you can put anywhere in your Silverlight page.

2) Progress Indicator – A control which lives in the System Tray.

Let’s start off by talking about the ProgressBar.

Progress Bar

The Progress Bar is not in the Visual Studio ToolBox by default, so, you will have to add it to the ToolBox in Visual Studio. To do this, Right-Mouse Click on the ToolBox and select “Choose Items…”. Then find “ProgressBar” and check its checkbox.

clip_image002_thumb2 clip_image004_thumb3

After a short delay, you will see the “ProgressBar” in the toolbox

image_thumb8

Now you can drag the ProgressBar control into your XAML Windows Phone pages. This will add code like the following to your XAML file.

<ProgressBar Name="progressBar1" Value="0"></ProgressBar>

You can then set the properties of the control as needed:

clip_image006_thumb1

To use this new ProgressBar in Determinate mode, make sure the IsIndeterminate checkbox is unchecked. Then you can set the Minimum, Maximum and Value properties of the control.

In the code behind as your operation is making progress, you change the Value property to the desired value between Minimum and Maximum. The Progress Bar will make sure the Value is always between the Minimum and the Maximum. You can fill up the Progress Bar simply by increasing the Value based on the progress of your operation.

Progress Indicator

Another way to show progress is by using a Progress Indicator. This control appears in the SystemTray as shown below. Here are pictures of the SystemTray and the Progress Indicator in the SystemTray.clip_image008_thumb2

clip_image010_thumb4

To use the Progress Indicator you must add this using statement to your code behind.

using Microsoft.Phone.Shell; 

 

You can then create a Progress Indicator and add it to the System Tray like this.

ProgressIndicator progressIndicator = new ProgressIndicator() {

IsVisible = true, IsIndeterminate = false,

Text = "Downloading file ..." };

SystemTray.SetProgressIndicator(this, progressIndicator);

 

Note that the Value property of the Progress Indicator must always be between 0 and 1. Where as for the ProgressBar, the Value property must be between the Minimum and the Maximum.

Sample App

Day15-ProgressBar is an App which tests both of these controls:

clip_image012_thumb2

Here’s an overview of the code:

The XAML code below show all of the controls we will use in our test. There is a ProgressBar to show the progress, a couple of buttons to Start or Stop a timer for the simulation, and a Slider which will be used to change the ProgressIndicator’s Value.

<phone:PhoneApplicationPage

x:Class="Day15_ProgressBar.MainPage"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"

FontFamily="{StaticResource PhoneFontFamilyNormal}"

FontSize="{StaticResource PhoneFontSizeNormal}"

Foreground="{StaticResource PhoneForegroundBrush}"

SupportedOrientations="Portrait" Orientation="Portrait"

shell:SystemTray.IsVisible="True">

<!--LayoutRoot is the root grid where all page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

<Grid.RowDefinitions>

<RowDefinition Height="Auto"/>

<RowDefinition Height="*"/>

</Grid.RowDefinitions>

<!--TitlePanel contains the name of the application and page title-->

<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">

<TextBlock x:Name="ApplicationTitle" Text="DAY 15" Style="{StaticResource PhoneTextNormalStyle}"/>

<TextBlock x:Name="PageTitle" Text="making progress" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}" FontSize="56" />

</StackPanel>

<!--ContentPanel - place additional content here-->

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

<StackPanel>

<TextBlock FontSize="36" Foreground="#FFDBE6FF" Name="textBlock3" Text="Progress Indicator" TextWrapping="Wrap" FontWeight="Bold" />

<TextBlock Name="textBlock1" Text="Drag the Slider to see the Progess In System Tray." FontSize="20" TextWrapping="Wrap" Foreground="#FFDBE6FF" />

<Slider Name="slider1" Width="Auto" Maximum="1" LargeChange="0.1" SmallChange="0.01" ValueChanged="slider1_ValueChanged" Margin="50,0" />

<TextBlock FontSize="36" Name="textBlock2" Text="Progress Bar" TextWrapping="Wrap" Foreground="#FFDBE6FF" Margin="0,50,0,0" FontWeight="Bold" />

<Button Name="StartButton" Content="Start the Timer" Click="Button_Click"></Button>

<Button Name ="StopButton" Content="Reset the Timer" Click="Button_Click_1"></Button>

<ProgressBar Name="progressBar1" Value="0" IsIndeterminate="False" Height="50" SmallChange=".5" LargeChange="10"></ProgressBar>

</StackPanel>

</Grid>

</Grid>

</phone:PhoneApplicationPage>

Here’s the C# Code Behind. Let’s walk through what the code to see what it is doing.

To begin with, we set up the using statements for the controls we are going to use. For the ProgressIndicator, we must use Microsoft.Windows.Shell. Then inside the class that was created for the page, we declare our global variables. A ProgressIndicator is created which we will later put into the SystemTray. A DispatcherTimer called timer is created which will be used to simulate a deterministic operation. In the constructor we put the newly created progressIndicator into the SystemTray and setup the timer to call the timer_Tick method every 5000 ticks.

using System;

using System.Windows;

using System.Windows.Threading;

using Microsoft.Phone.Shell;

namespace Day15_ProgressBar

{

public partial class MainPage

{

ProgressIndicator progressIndicator = new ProgressIndicator() { IsVisible = true, IsIndeterminate = false, Text = "Downloading file ..." };

DispatcherTimer timer = new DispatcherTimer();

// Constructor

public MainPage()

{

InitializeComponent();

SystemTray.SetProgressIndicator(this, progressIndicator);

timer = new DispatcherTimer {Interval = new TimeSpan(5000)};

timer.Tick += timer_Tick;

timer.Stop();

}

}

}

 

When the timer fires and the timer_Tick method is called, we add a value to the ProgressBar’s Value Property to make it seem like the operation is making progress.

Below that method is the Button Click event handlers. They start and stop the timer, so that we can simulate a long operation deterministic operation. Pressing the Start button resets the progressBar1’s Value property to 0 and starts the timer. Pressing the Stop button also resets the progressBar1’s Value property to 0, but this time we Stop the timer from progressing.

The last method in the class is the event handler slider1_ValueChanged that is called when the slider is moved. We will use the slider value to position the ProgressIndicator.

using System;

using System.Windows;

using System.Windows.Threading;

using Microsoft.Phone.Shell;

namespace Day15_ProgressBar

{

public partial class MainPage

{

// Constructor

ProgressIndicator progressIndicator = new ProgressIndicator() { IsVisible = true, IsIndeterminate = false, Text = "Downloading file ..." };

DispatcherTimer timer = new DispatcherTimer();

public MainPage()

{

InitializeComponent();

SystemTray.SetProgressIndicator(this, progressIndicator);

timer = new DispatcherTimer {Interval = new TimeSpan(5000)};

timer.Tick += timer_Tick;

timer.Stop();

}

void timer_Tick(object sender, EventArgs e)

{

progressBar1.Value += progressBar1.SmallChange;

}

private void Button_Click(object sender, RoutedEventArgs e)

{

progressBar1.Value = 0;

timer.Start();

}

private void Button_Click_1(object sender, RoutedEventArgs e)

{

timer.Stop();

progressBar1.Value = 0;

}

private void slider1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)

{

progressIndicator.Value = e.NewValue;

}

}

}

Summary

So that’s how you use Progress Bars in a Windows Phone Mango application. In a few lines of code you can quickly add full featured Progress Bars to any Silver Light Windows Phone application. You can create a ProgressIndicator which you can put into the SystemTray, or you can create a ProgressBar which you can display anywhere on the applications page.

Progress Bars are essential to applications with lengthy operations. It gives the user a feeling that the application is working for them and will be back to them when the operation completes. Your users will feel better about waiting when they are informed on the applications progress.

To download a working version of the application that was built in this article, please click the Download Code button below:

download

Tomorrow, we are going to look at the Isolated Storage Explorer, which allows you to look at and inspect the data you have stored in Isolated Storage in your emulator.  Samidip Basu will show you the hows and whys of this new feature.  See you then!

toolsbutton



Source: http://www.jeffblankenburg.com/2011/11/15/31-days-of-mango-day-15-the-progress-bar

Published at DZone with permission of Jeff Blankenburg, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)