Create a Simple Progress Bar Control In Silverlight 2
Note: This article is written based on a pre-release version of Silverlight and could change in future.
This article discusses how to create a simple progress bar in Silverlight 2 Beta 2. We will download a .zip file and display the progress of the download using a progress bar.
If you are not familiar with hosting Silverlight 2 in ASP.NET, I would suggest you to read my previous articles which talks about the basics and prerequisites of creating Silverlight applications. Assuming you have some experience in creating Silverlight 2 applications, let us see the steps involved to create a progress bar in Silverlight.
Step 1: Open Visual Studio 2008 > File > New Project > Select the language (C# or VB) > Select ‘Silverlight’ in the Project Types > from the templates, select ‘Silverlight Application’. Type a name ‘ProgressBarSilverlight’ (for VB.NET users - ProgressBarSilverlightVB) and location for the project and click ok.
Note: If you are unable to view the templates, you do not have Microsoft Silverlight Tools Beta 2 for Visual Studio 2008. Please check this article on how to install these templates.
Step 2: You will observe that a default page called ‘Page.xaml’ gets created. Set the Width and Height of the user control to 400 & 300 respectively. Remove the <Grid> and replace it with <Canvas>.
Step 3: The XAML mark up shown below creates an outer Rectangle and an inner Rectangle. The outer Rectangle sets the boundary of the horizontal progress bar with a black colored boundary and a width of 200. The Inner Rectangle (rectInner) is filled using a LinearGradientBrush and I have used a few GradientStops to fill it with multiple colors. As you may realize, I keep proving that I am only a developer and not a designer, by creating lousy designs. Pardon me once again.
When the application is run and the user clicks on the ‘Download’ button, the inner Rectangle (rectInner) starts with a width of 0 and is incremented using the percentage from the DownloadProgressChanged event handler. It continues increasing till its width reaches 100%. The mark up is as shown below:
<UserControl x:Class="ProgressBarSilverlight.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Canvas Canvas.Top="100">
<Rectangle x:Name="rectOuter"
Canvas.Top ="5"
Canvas.Left="10" Height="15"
Width="100"
StrokeThickness="1" Stroke="Black" />
<Rectangle
Name="rectInner"
Canvas.Left="10" Canvas.Top="5"
Height="15"
>
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Color="Blue" Offset="0.1"/>
<GradientStop Color="White" Offset="0.4"/>
<GradientStop Color="Blue" Offset="0.6"/>
<GradientStop Color="White" Offset="0.8"/>
<GradientStop Color="Blue" Offset="1.0"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<TextBlock
x:Name="tbProgress"
Canvas.Top ="5" Canvas.Left="130"
Text="0% Completed" FontSize="11" />
<Button x:Name="btnDownld" Canvas.Top="30" Canvas.Left="30"
Click="btnDownld_Click" Content="Download"/>
</Canvas>
</UserControl>
The UI will look similar to the following:
Step 5: Before adding some code to make the progress bar functional, add an image.zip to your \ClientBin folder (If you cannot see the ClientBin, just compile the application once). I would advise you to keep the size of the image.zip greater than 5 MB. This would take some time to download and you will be able to view the progress bar.
Silverlight provides us with the WebClient class which gives us the ability to download data asynchronously. The WebClient class contains events to initiate the request, track the progress of the request, and retrieve the data. The code mentioned below shows how to use these events:
Before that, add the following namespaces:
C#
using System.Windows.Resources;
using System.Windows.Media.Imaging;
using System.IO;
VB.NET
Imports System.Windows.Resources
Imports System.Windows.Media.Imaging
Imports System.IO
The code for the using the events of the WebClient class are as follows:
C#
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
}
private void btnDownld_Click(object sender, RoutedEventArgs e)
{
WebClient wClient = new WebClient();
wClient.OpenReadCompleted += new OpenReadCompletedEventHandler(wClient_OpenReadCompleted);
wClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wClient_DownloadProgressChanged);
wClient.OpenReadAsync(new Uri("image.zip",UriKind.Relative));
}
void wClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
// gets the downloaded percentage of the async operation
tbProgress.Text = e.ProgressPercentage.ToString() + "% completed";
rectInner.Width = (double)e.ProgressPercentage;
}
void wClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error == null)
{
try
{
Stream streamZip = e.Result;
StreamResourceInfo sri = new StreamResourceInfo(streamZip, null);
// Assuming abc.jpg is an image inside the image.zip
StreamResourceInfo imageSourceInfo =
Application.GetResourceStream(sri, new Uri("abc.jpg", UriKind.Relative));
// Converting the stream to Image
BitmapImage bi = new BitmapImage();
Image img = new Image();
img.Source = bi;
// Do something with this image
}
catch (Exception ex)
{
}
}
}
}
VB.NET
Public Partial Class Page
Inherits UserControl
Public Sub New()
InitializeComponent()
End Sub
Private Sub btnDownld_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Dim wClient As WebClient = New WebClient()
AddHandler wClient.OpenReadCompleted, AddressOf wClient_OpenReadCompleted
AddHandler wClient.DownloadProgressChanged, AddressOf wClient_DownloadProgressChanged
wClient.OpenReadAsync(New Uri("image.zip",UriKind.Relative))
End Sub
Private Sub wClient_DownloadProgressChanged(ByVal sender As Object, ByVal e As DownloadProgressChangedEventArgs)
' gets the downloaded percentage of the async operation
tbProgress.Text = e.ProgressPercentage.ToString() & "% completed"
rectInner.Width = CDbl(e.ProgressPercentage)
End Sub
Private Sub wClient_OpenReadCompleted(ByVal sender As Object, ByVal e As OpenReadCompletedEventArgs)
If e.Error Is Nothing Then
Try
Dim streamZip As Stream = e.Result
Dim sri As StreamResourceInfo = New StreamResourceInfo(streamZip, Nothing)
// Assuming abc.jpg is an image inside the image.zip
Dim imageSourceInfo As StreamResourceInfo = Application.GetResourceStream(sri, New Uri("abc.jpg", UriKind.Relative))
' Converting the stream to Image
Dim bi As BitmapImage = New BitmapImage()
Dim img As Image = New Image()
img.Source = bi
' Do something with this image
Catch ex As Exception
End Try
End If
End Sub
In the code above, on button click, we create an instance of the WebClient for the requesting the .zip file. We then add the event handlers for ‘OpenReadCompleted’ and ‘DownloadProgressChanged’ events. The ‘OpenReadAsync’ initiates the request by passing in the location of the resource to be downloaded, in our case the image.zip file.
The ‘DownloadProgressChanged’ event updates the progress bar created earlier in the XAML markup. The progress is updated by using the e.ProgressPercentage property as a Double value between 0 and 100.
Finally, in the ‘OpenReadCompleted’, we process the initial stream and use the Application.GetResourceStream to get a specific part (abc.jpg) from a location in the zip file. When the application is run, some of the stages of the progress bar will visually look similar to the following images:
In this article, we saw how we can create a simple progress bar and visually display the download progress while we download a zip file. You can extend this sample and reuse the progress bar to create an image viewer application with a progress indicator. I hope this article was useful and I thank you for viewing it.
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of
DotNetCurry,
DNC Magazine for Developers,
SQLServerCurry and
DevCurry. He has also authored a couple of books
51 Recipes using jQuery with ASP.NET Controls and
The Absolutely Awesome jQuery CookBook.
Suprotim has received the prestigious Microsoft MVP award for Sixteen consecutive years. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that offers Digital Marketing and Branding services to businesses, both in a start-up and enterprise environment.
Get in touch with him on Twitter @suprotimagarwal or at LinkedIn