Fredrik Normén's Blog - NSQUARED²
Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

Microsoft Most Valuable Professional
     .Net Framework - ASP.Net - Architecture - Development
NOTE: This list of posts will only list the 15 latest posts, to see the rest, select from the Archives located in the menu to the left. The RSS will only list the 10 lastest posts.
The Downloader object

Category:  Silverlight

This will be my first post about some Silverlight code. In this post I will write about how we can easy use the Downloader object shipped with Silverlight, and display a progress bar that will show us the progress of the download. I decided to use Microsoft Expression Blend 2 when I created the code in this post. You can get the current preview version of Expression Blend at the following site: http://silverlight.net/GetStarted/

The application uses Silverlight 1.0 and not 1.1 because 1.1 is still in a alpha version at the time I created this post.

The Downloader object.

With Silverlight we will have an object called the Downloader object which we can use to download content on the fly. Maybe we don’t want to have all the data for our Silverlight loaded when the app is initialized, instead load content on demand etc. It’s very easy to use the Downloader object in our code.  To create an instance of the Downloader object we use the createObject method which can for example be accessible from the Silverlight host/plugin object, and we pass the string “downloader” (the name of the object to create) as an argument to the createObject method:

var plugin = document.getElementById("SilverlightPlugIn");
var downloader = plugin.createObject("downloader");

Note: We can also get the host object by using the getHost() method, in my example I will use the getHost method.

When we have an instance of the Downloader object we can start to use it, the first thing to do is to hook up to at some events that the downloader object has, such as the “downloadProgressChanged” and the “completed” event. The “downloadProgressChanged” can be used to check the current state of the downloaded content, this is the event we can use to update our progress bar etc. The “completed” event will of course be trigged when the download is completed. It will be from the “completed” event we will get the downloaded content. To get the downloaded content we can use several methods, such as the Downloader object’s ReponseText to get the downloaded content as a text, or we can use some UI elements methods like SetSource etc. I will use the SetSource of the MediaElement in my example to set the source of a MediaElement to my downloaded content. To set up the “downloadProgressChanged” and “completed” event, we can use the Downloader object’s addEventListener method:

downloader.addEventListener("downloadProgressChanged", onDownloadProgressChanged);
downloader.addEventListener("completed", onCompleted);

The first argument the addEventListener takes is the name of the event we will bind a “method” to. The last argument is the name of the method that should be executed when the event is trigged.

Now when we have added the events we can use the Downloader object to start downloading some content. To download content we use the open method and the send method of the Downloader object. With the open method we specify that we want to get a specific file from our domain (in this case the files in our application folders):

downloader.open("GET", "thebutterflyandthebear.wmv");

I will in this example download the ”thebutterflyandthebear.wmv” media filed shipped with the Silverligth SDK.

When we have specified which file to download we must send the request to start the download, this is done by calling the Downloader object’s send method:

downloader.send();

Before I move on about how to get the downloaded content I will first show you the XAML code of my progress bar that is used in this example:

<canvas …>
   <Canvas Name="myProgressBar" Width="404" Height="28" Opacity="0" Canvas.Left="125"    Canvas.Top="144">
     <Rectangle Width="404" Height="28" Stroke="#FFFFFFFF" StrokeThickness="2">
        <Rectangle.Fill>
           <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
              <GradientStop Color="#FF000000" Offset="0"/>
              <GradientStop Color="#FF18244A" Offset="1"/>
          </LinearGradientBrush>
        </Rectangle.Fill>
  </Rectangle>

   <Rectangle Name="progressBar" Opacity="0.86" Width="0" Height="24" Stroke="#FF000000" StrokeThickness="2" Canvas.Left="2" Canvas.Top="2">
     <Rectangle.Fill>
         <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
              <GradientStop Color="#FF000000" Offset="0"/>
              <GradientStop Color="#FF8899DD" Offset="1"/>
        </LinearGradientBrush>
     </Rectangle.Fill>
   </Rectangle>

   <MediaElement Name="myMediaPlayer" Width="467" Height="341" Canvas.Left="101"    Canvas.Top="85" Stretch="Fill"/>
<canvas>

   <TextBlock Name="progressText" Width="71" Height="24" Canvas.Left="182" Canvas.Top="2" Foreground="#FFFFFFFF" Text="" TextWrapping="Wrap"/>
</Canvas>

The progress bar is grouped into an own canvas where I have used two rectangles, one for the “border” and one for the progress indication itself (the name of the rectangle is set to “progressBar”). I have also added a TextBlock (progressText) that will show in percentage how much data that is currently downloaded during the download progress. There is also a MediaElement added to the application, this will be used to display the downloaded media file.

Now let take a look at the implementation of the “downloadProgressChanged” and the “completed” event. The events will have two arguments, the sender (which in this case will the Download object) and eventArgs wich have some event argument information. Here is the code for the “downloadProgressChanged” event:

function onDownloadProgressChanged(sender, eventArgs)
{
    var plugin = sender.getHost();

    var percentage = Math.floor(sender.downloadProgress * 100);

    var progressText = plugin.content.findName("progressText");
    var progressBar = plugin.content.findName("progressBar");

    progressText.text = percentage + "%";
    progressBar.width = percentage * 4;
}

By using the getHost method of the sender argument, we can get the Silverlight host object. I will use host object find the element that I will update, like the Rectangle that should show the progress bar and the text with the percentage of how much data that is currently downloaded. By using the Downloader object’s downloadProgress property times 100 we can get the percentage of the current downloaded content. I will use this value to update the TextBlock “progressText”, I will also use the value to increase the progress bar width.

In the onCompleted method we can get the data that the Downloaded object has downloaded:

function onCompleted(sender, eventArgs)
{
    var plugin = sender.getHost();

    var progressText = plugin.content.findName("progressText");

    progressText.text = "Done";


    var myMediaPlayer = plugin.content.findName("myMediaPlayer");

    myMediaPlayer.setSource(sender, "");
    myMediaPlayer.play();
}

To get the downloaded content from the Downloaded object I have used the MediaElement’s setSource method. This method takes two arguments, the Downloader object which have the media content that should be the source of the MediaElement, and the second one is the name of a file within a .zip file. If we use the Downloader object’s open method and point to a .zip file, we need to specify which file within the .zip file we want to set as a source to the MediaElement. When we download one file we pass an empty string as the second argument.

Here is the live demo of the application:
http://fredrik.nsquared2.com/silverlight/downloadcontent/default.html

Here is the source code for the application:
http://fredrik.nsquared2.com/silverlight/downloadcontent/downloadcontent.zip

Posted: Wednesday, October 03, 2007 - 11:45 GMT+1    Print     E-mail    Comments (5)
   fredrik.nsquared2.com - 2007