| Comments

one really great feature about silverlight is the packaging aspect of it.  what do i mean by this?  well, you can essentially put a ton of assets into a compressed file and pull them out as needed.  this would provide you the ability to have a single asset package that is compressed, and thus saving on some download time.  of course there would be tradeoffs that you'd have to consider, but for sample sake, let's assume they are good.

so how would you do that?  well let's say you have a bunch of images in a file name 'assets.zip' (here we have 2):

in our silverlight application we want to load those up and then maybe use them individually later at some point in an event.  here's the xaml i'm working with for this sample:

   1:  <Canvas
   2:      xmlns="http://schemas.microsoft.com/client/2007"
   3:      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:      Width="605" Height="314"
   5:      >
   6:      <Rectangle Stroke="#FF000000" x:Name="progressBar" Width="0" Height="18" Canvas.Top="1">
   7:          <Rectangle.Fill>
   8:              <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
   9:                  <GradientStop Color="#FFCAE8B0" Offset="0"/>
  10:                  <GradientStop Color="#FF68C51A" Offset="1"/>
  11:              </LinearGradientBrush>
  12:          </Rectangle.Fill>
  13:      </Rectangle>
  14:      <Rectangle Stroke="#FF000000" Width="600" Height="18" Canvas.Top="1"/>
  15:      <Image x:Name="logoImage" Width="318" Height="204" Canvas.Left="282" Canvas.Top="23"/>
  16:      <Canvas Width="117" Height="28" Canvas.Top="64" MouseLeftButtonUp="handleButton2Click">
  17:          <Rectangle Stroke="#FF000000" RadiusX="4" RadiusY="4" x:Name="buttonPicture2" 
Width="117" Height="25" >
  18:              <Rectangle.Fill>
  19:                  <LinearGradientBrush EndPoint="0.613,-1.095" StartPoint="0.503,1.975">
  20:                      <GradientStop Color="#FF58DD65" Offset="0.067"/>
  21:                      <GradientStop Color="#FF42BBB8" Offset="1"/>
  22:                  </LinearGradientBrush>
  23:              </Rectangle.Fill>
  24:          </Rectangle>
  25:          <TextBlock Width="57" Height="25" FontFamily="Calibri" FontSize="14" Text="Picture 2" 
                     Canvas.Left="33" Canvas.Top="3"/>
  26:      </Canvas>
  27:      <Canvas Width="118" Height="28" Canvas.Top="23" MouseLeftButtonUp="handleButton1Click">
  28:          <Rectangle Stroke="#FF000000" RadiusX="4" RadiusY="4" Width="118" Height="25" 
                     x:Name="buttonPicture1" >
  29:              <Rectangle.Fill>
  30:                  <RadialGradientBrush>
  31:                      <GradientStop Color="#FFDDB758" Offset="0.067"/>
  32:                      <GradientStop Color="#FFBBAF42" Offset="1"/>
  33:                  </RadialGradientBrush>
  34:              </Rectangle.Fill>
  35:          </Rectangle>
  36:          <TextBlock Width="57" Height="25" Canvas.Left="33" Canvas.Top="3" FontFamily="Calibri" 
                     FontSize="14" Text="Picture 1"/>
  37:      </Canvas>
  38:      <TextBlock x:Name="percentComplete" Width="110" Height="27" Canvas.Top="96" 
                     FontFamily="Calibri" FontWeight="Bold" Text="" TextWrapping="Wrap"/>
  39:  </Canvas>

i'm using the javascript programming model here and my xaml file has an associated javascript file that looks like this (minus the silverlight creation script):

   1:  var dl = null;
   2:   
   3:  function onDownloadProgressChanged(sender, eventArgs)
   4:  {
   5:      var pcnt = Math.floor(sender.downloadProgress * 100);
   6:      
   7:      sender.findName("progressBar").width = sender.downloadProgress * 600;
   8:      sender.findName("percentComplete").text = sender.downloadProgress * 100 + "%";
   9:  }
  10:   
  11:  function onDownloadCompleted(sender, eventArgs)
  12:  {
  13:      var img = sender.findName("logoImage");
  14:      img.setSource(sender, "PIC_0004.jpg");
  15:  }
  16:   
  17:  function initDownloader(host)
  18:  {
  19:      dl = host.createObject("downloader");
  20:      
  21:      dl.addEventListener("downloadProgressChanged", "onDownloadProgressChanged");
  22:      dl.addEventListener("completed", "onDownloadCompleted");
  23:      
  24:      dl.open("GET", "timfaces.zip", true);
  25:      
  26:      dl.send();
  27:  }
  28:   
  29:  function resetImage(host, imgName)
  30:  {
  31:      var img = host.content.findName("logoImage");
  32:      
  33:      if (!dl) { initDownloader(host); }
  34:      
  35:      img.setSource(dl, imgName);
  36:  }
  37:      
  38:  function handleButton1Click(sender, eventArgs)
  39:  {
  40:      var host = sender.getHost();
  41:   
  42:      resetImage(host, "PIC_0004.jpg");
  43:  }
  44:   
  45:  function handleButton2Click(sender, eventArgs)
  46:  {
  47:      var host = sender.getHost();
  48:      
  49:      resetImage(host, "PIC_0012.jpg");
  50:  }

notice the two events wired up on initDownloader and the two callback events that happen when those events are completed.

take a look at the function onDownloadCompleted...this is where we leverage the compressed asset file.  for this sample, we want to use images.  so basically we are setting an image object source to an item in the zip file.  we first find the associated element, then setSource providing the name which resides in the zip file.  that's it, we are done!

in my sample here, i chose to implement "dl" as a global variable so i could access it later.  while at MIX this week i was able to get some better practices of wiring up some object prototypes and include the downloader as an object essentially of the other javascript objects.  i know it sounds confusing.  open up blend 2 preview and start a project, look at the scene.xaml.js file and you'll see what i mean...it really isn't that confusing.  i just had this working sample and wanted to share.

the concept of using a downloader in conjunction with a compressed asset file intrigues me and i hope you may find it useful.  now this isn't the only way you could use this method (picture assets), as i believe the intent actually was more of a packaging concept intended for xaml files that you can pull out and load. as an example, in the onDownloadCompleted let's assume i had a file in there called newFunction.xaml that was there for some additional layouts, etc.  i could do something like this (again, assuming in the onDownloadCompleted method):

var newXaml = sender.getResponseText("newFunction.xaml");

then with that text i can do some createObjectFromXaml functions or something like that.  pretty cool.

have fun, check out today.

Please enjoy some of these other recent posts...

Comments