Master pages, part V : progressive download of pages with a heavy footprint

by gleblanc 16. February 2009 01:29

In previous posts, we showed how to progressively load (in the background) the different pages of a Silverlight application, drastically reducing the wait time for the user. Here, we go a step further : some pages have a heavy footprint (ie their xap files are big), generally because they need support from one or more dll's (these dll's are then incorporated by Visual Studio into the xap file). 

Here, we are using the Chart control from the Toolkit (http://www.codeplex.com/Silverlight ) in the first page. To do so, we need to add a reference to Microsoft.Windows.Controls.DataVisualization.dll, which is a 280 KB file. Using the progressive download technique, our first page is only 12 KB and is thus displayed immediately after request. 

Background images are paintings from Georgia O'Keeffe, an American artist. 


Project / source code

As usual, we create a Silverlight project (SilverlightApplication5). The default page contains the master page, but not its background image, that will dynamically loaded (ie by program, later on) :

 <Grid>
  <Image x:Name="imgBG" Stretch="UniformToFill"  />
  <Grid x:Name="LayoutRoot" Background="LightGray" >
  .....  here the xaml for master page
  </Grid>
 </Grid>   

The master page contains a grid cell (named PageContainer) that will act as a place-holder for Page1, Page2 and Page3 (one at a time). 

Within the same project (the only one right now), we create Page1 (Add, New Item, Silverlight UserControl). The background image and the Chart control are not included (we just mention a grid cell as place-holder, named PlaceHolderForChart). The master page and Page1 are compiled into the same xap file (SilverlightApplication5.xap, whose size is only 12 KB).

In the solution, we add a new project (right click on the Solution line, Add, New Project), first for Page2 (project named Proj4Page2). Then for Page3 (Proj4Page3). Page2 and Page3 are build as usual. After compilation, Proj4Page2.xap and Proj4Page3.xap are created (10 KB each) in the ClientBin folder.   

To keep data available to and from any page, we create another project (named Proj4Data) in the solution. We keep data as public static fields in Proj4Data.Page.xaml.cs. Upon confirmation in Page2 and Page3 (button Confirm), legends and slider values are saved in fields of Proj4Data (for instance Proj4Data.Page.LegendPage2, of type string).

Now the most interesting part for this post : we create a new project named Proj4Chart. We add a reference to Microsoft.Windows.Controls.DataVisualization.dll (a 280 KB file downloaded with the toolkit). We insert a Chart control in Proj4Chart.xaml :

 <UserControl x:Class="Proj4Chart.Page"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml
   xmlns:chart="clr-namespace:Microsoft.Windows.Controls.DataVisualization.Charting;
                assembly=Microsoft.Windows.Controls.DataVisualization"
  >
  <Grid x:Name="LayoutRoot" >
   <StackPanel Orientation="Vertical"  >
    <chart:Chart x:Name="chart" LegendTitle="Legend" BorderThickness="0"
                Width="250" Height="225" >
     <chart:Chart.Series>
      <chart:PieSeries DependentValueBinding="{Binding Path=Value}"
                       IndependentValueBinding="{Binding Path=Key}"
                       BorderThickness="0" />
     </chart:Chart.Series>
    </chart:Chart>
   </StackPanel>
  </Grid>
 </UserControl>

We add a using line in Proj4Chart.xaml.cs, as well as a function (DrawChart) :

 .....
 using Microsoft.Windows.Controls.DataVisualization.Charting;  namespace Proj4Chart
 {
  public partial class Page : UserControl
  {
   public Page()
   {
    InitializeComponent();
    .....    // initialisation of a delegate to DrawChart
   }
   public void DrawChart()
   {
    PieSeries serie = chart.Series[0] as PieSeries;
    serie.ItemsSource = new KeyValuePair<string, int>[] {
      new KeyValuePair<string, int>(Proj4Data.Page.LegendPage2,
                                    Proj4Data.Page.SliderValuePage2),
      new KeyValuePair<string, int>(Proj4Data.Page.LegendPage3,
                                    Proj4Data.Page.SliderValuePage3)
     };
   }
  }
 }

We will explain the initialisation of the delegate to DrawChart at the end of this post.

In the projects named SilverlightApplication5, Proj4Page2, Proj4Page3 and Proj4Chart, we add a reference (right click on the project line, Add Reference, Projects) to Proj4Data (Proj4Data.xap is a 5 KB file). 

In the constructor of the master page (SilverlightApplication5.xaml.cs), we initiate the progressive download (in the background) of (in sequence, in this order) : background image for master page, Proj4Page2.xap, Proj4Page3.xap, Proj4Chart, background image for Page1, background image for Page2 and background image for Page3. These two xap files and these four jpg files must be copied in the ClientBin folder.  

We explained in a previous post how to extract a UserControl out of Proj4Page2.xap and Proj4Page3.xap.

Proj4Chart.xap is a bit more complex since it contains an additional (and huge) file : Microsoft.Windows.Controls.DataVisualization.dll. For confirmation, rename Proj4Chart.xap as Proj4Chart.zip and unzip it. In AppManifest.xaml, you will find an additional line : 
 <AssemblyPart x:Name="Microsoft.Windows.Controls.DataVisualization"
               Source="Microsoft.Windows.Controls.DataVisualization.dll" />

The work for Proj4Chart is not so different (see previous posts) : 

 void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
 {
  .....
  StreamResourceInfo sri, sri4dll;
  AssemblyPart asmPart, asmPartChart;
  Assembly asm;
  UserControl uc;
  switch (nStep)
  {
   case 1:             // end of load for background image of masterpage
     .....
   case 2:             // end of load of Page2.xap
     .....
   case 3:             // end of load of Page3.xap
     .....
     nStep++;
     // load Proj4Chart.xap (includes Microsoft.Windows.Controls.DataVisualization.dll)
     client.OpenReadAsync(new Uri("Proj4Chart.xap", UriKind.Relative));
     break;
   case 4:             // end of load of Proj4Chart
     sri = new StreamResourceInfo(e.Result, null);
     sri4dll = Application.GetResourceStream(sri,
                  new Uri("Microsoft.Windows.Controls.DataVisualization.dll",
                          UriKind.Relative));
     asmPartChart = new AssemblyPart();
     asmPartChart.Load(sri4dll.Stream);
     sri4dll = Application.GetResourceStream(sri,
                 new Uri("Proj4Chart.dll", UriKind.Relative));
     asmPart = new AssemblyPart();
     asm = asmPart.Load(sri4dll.Stream);
     uc = asm.CreateInstance("Proj4Chart.Page") as UserControl;
     Proj4Data.Page.chart = uc;
     page1.PlaceHolderForChart.Children.Add(uc);
     nStep++;
     // load background image for Page1
     .....
     break;
   case 5:             // end of load for background image for page1
     .....
   case 6:             // end of load of background image for page2
     .....
   case 7:             // end of load of background image for page3
     .....
  }
 }

The xap file is first loaded into sri, of type StreamResourceInfo. From sri, we extract first DataVisualization.dll, that we load in a newly created object (asmPartChart) of type AssemblyPart. It's all, folks! For Proj4Chart.dll (that contains xaml and C# compiled code), nothing is changed from the previous post.

To end this post : how do we call the DrawChart function in Proj4Chart.Page.xam.cs from any page ? In Proj4Data.Page.xaml.cs (that contains shared variables), we declare a delegate :

 public delegate void DrawChartDel();
 public static DrawChartDel fDrawChart;   

A delegate is the C# (type-safe) equivalent of C function pointer, ie a variable that holds the address of a function. It's possible to call the function thru the function pointer. In the first line, we define a type : a variable of type DrawChartDel is (in C parliance) a variable that points to a function that accepts no argument and returns nothing (void). In the second line, we declare such a variable, here named fDrawChart.

Up to now, fDrawChart points to nothing. fDrawChart is initialized in the constructor in Proj4Chart.Page.xaml.cs :

 using Microsoft.Windows.Controls.DataVisualization.Charting; namespace Proj4Chart
 {
  public partial class Page : UserControl
  {
   public Page()
   {
    InitializeComponent();
    Proj4Data.Page.fDrawChart = new Proj4Data.Page.DrawChartDel(DrawChart);
   }
   public void DrawChart()
   {
    .....
   }
  }
 }

To call DrawChart from Page2, we just need to write :

 if (Proj4Data.Page.fDrawChart != null) Proj4Data.Page.fDrawChart(); 

In the forthcoming post, a similar example with a web service request. See you soon. A+, as we now say in the new sms-biaised French language. 

Tags:

Comments

2/17/2009 7:48:28 AM #

Trackback from Community Blogs

Silverlight Cream for February 16, 2009 -- #519

Community Blogs

7/14/2009 3:04:19 PM #

Would you like to post a guest post on my blog?

Lucien Piccard United States

7/20/2009 1:37:59 PM #

Very nice post. Quite informative.

HIV Symptoms United States

7/24/2009 9:26:24 PM #

Would you like to post a guest post on my blog?

Charles Hubert United States

8/5/2009 6:44:53 AM #

good good�this post deserves nothing Frown  �hahaha just joking Tong �nice post Tong

payday loans United States

8/5/2009 6:44:57 AM #

In searching for sites related to web hosting and specifically comparison hosting linux plan web, your site came up.

payday loans United States

8/11/2009 3:40:09 AM #

Hello. Great job. I did not expect this on a Wednesday. This is a great story. Thanks!

cash loans United States

9/3/2009 8:10:19 PM #

Normal Blog.Like it!

payday loans United States

9/15/2009 4:05:39 AM #

Thank you very this news was very useful for me!

alternative medicine Spain

9/17/2009 12:39:10 PM #

Reducing wait time for me is paramount. I am building a whole new application for my dating website, and this will help my New Jersey members have a better experience.

New Jersey Dating United States

9/17/2009 7:27:08 PM #

how to get your blog to show up on search engine?

how long does weed stay in your system United States

9/21/2009 1:57:07 PM #

true there!

Weber Grill Accessories Ukraine

9/24/2009 8:16:17 PM #

Very interesting discussion, I got a lot of things from here.

Oes Tsetnoc United States

9/28/2009 5:02:53 PM #

I recently came across your blog and have been reading along. I thought I would leave my first comment. I don't know what to say except that I have enjoyed reading. Nice blog. I will keep visiting this blog very often.

build outdoor fireplace Russia

10/1/2009 10:50:33 AM #

Forums at silver light is the best place to learn more about Master pages, visit:
http://forums.silverlight.net/forums/t/11079.aspx

web developer dubai U.A.E.

10/2/2009 4:16:06 PM #

You made some good points there. I did a search on the topic and found most people will agree with your blog.

personal loan United States

10/2/2009 4:16:08 PM #

Hello, I found your blog in a new directory of blogs. I dont know how your blog came up, must have been a typo, Your blog looks good. Have a nice day.

personal loan United States

10/3/2009 9:38:44 AM #

Very nice post

Contador de Visitas Gratis Brazil

10/3/2009 7:11:47 PM #

Thank you for this Smile

baby bouncer chair United States

10/7/2009 10:34:47 PM #

Would you like to post a guest post on my blog?

Receitinhas Brazil

10/8/2009 8:41:50 PM #

excellent tutorial.i liked it much and have bookmarked it too.

quick memorization United States

10/10/2009 1:22:54 AM #

You made some good points there. I did a search on the topic and found most people will agree with your blog.

cash loans United States

Powered by BlogEngine.NET 1.5.0.7
Theme by Mads Kristensen

About the author

Gerard Leblanc is the author of several books (in french) on C++, C#, .NET and Silverlight (Eyrolles, Paris as publisher). See www.gleblanc.eu as the companion web site for these books (included sample programs).
He is Microsoft MVP for Silverlight.

MVP logo