Silverlight:利用异步加载Xap实现自定义loading效果

               虽然在silverlight中微软自带了加载了silverlight项目时加载进度,但是如何自己定义加载精度条呢?本篇学习了如何自定义自己的加载进度条!本篇参考了http://www.cnblogs.com/yjmyzz/archive/2009/12/22/1629947.html这篇文章!

(一)关键点:
1.利用WebClient的DownloadProgressChanged事件更新下载进度
2.下载完成后,分析Xap包的程序集Assembly信息

3.利用Assembly反射还原对象并加载到当前页中。 

(二)好处:
1.可以先定义一个简单的加载动画,吸引用户注意,避免长时间的无聊等待,改善用户体验。
2.实现按需加载,避免一次性下载过多内容。

3.在一定程度上,增加了破解难度,有助于代码保密。

(三)项目实现:

(1)项目结构如下

(2)项目说明:

   LoadXap使来显示加载的进度条的,而MainXap是我们要加载的Xap包,里面的MainPage中包含一个Image空间(显示一张图片),当进度条加载完毕后将,MainXap中的MainPage加到LoadXap中MainPage中。 这样就是实现了加载异步加载xap中的Page或者用户空间了!

  值得注意的地方:在LoadXap项目中应添加MainXap.dll的引用,不然在 Assembly assembly = GetAssemblyFromXap(e.Result, "MainXap.dll");时会找不到该MainXap.dll程序集的。会报错的。

(3)项目LoadXap中主要代码

       MainPage.xaml中的代码:

代码
<Grid x:Name="LayoutRoot">
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Orientation="Horizontal">
<ProgressBar Height="15" VerticalAlignment="Center" HorizontalAlignment="Center" Width="200" x:Name="pb1" Value="0"/>
<TextBlock x:Name="txtLoad" Text="0%" Margin="5,0,0,0"></TextBlock>
</StackPanel>
</Grid>

      MainPage.xaml.cs的代码:

 

代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
//添加命名空间
using System.Windows.Browser;
using System.IO;
using System.Text.RegularExpressions;
using System.Reflection;
using System.Xml;
using System.Windows.Resources;

namespace LoadXap
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
WebClient wc
= new WebClient();
wc.OpenReadCompleted
+= new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
wc.DownloadProgressChanged
+= new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
Uri xapUri
= new Uri(HtmlPage.Document.DocumentUri, "ClientBin/MainXap.xap");
wc.OpenReadAsync(xapUri);
}

void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
this.txtLoad.Text = e.ProgressPercentage.ToString() + "%";
this.pb1.Value = (double)e.ProgressPercentage;
}

void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
Assembly assembly
= GetAssemblyFromXap(e.Result, "MainXap.dll");
UIElement element
= assembly.CreateInstance("MainXap.MainPage") as UIElement;
this.LayoutRoot.Children.Add(element);
}


/// <summary>
/// 从XAP包中返回程序集信息
/// </summary>
/// <param name="packageStream"></param>
/// <param name="assemblyName"></param>
/// <returns></returns>
private Assembly GetAssemblyFromXap(Stream packageStream, String assemblyName)
{
Stream stream
= Application.GetResourceStream(new StreamResourceInfo(packageStream, null), new Uri("AppManifest.xaml", UriKind.Relative)).Stream;
Assembly asm
= null;
XmlReader xmlReader
= XmlReader.Create(stream);
xmlReader.MoveToContent();
if (xmlReader.ReadToFollowing("Deployment.Parts"))
{
string str = xmlReader.ReadInnerXml();
Regex reg
= new Regex("x:Name=\"(.+?)\"");
Match match
= reg.Match(str);
string sName = "";
if (match.Groups.Count == 2)
{
sName
= match.Groups[1].Value;
}
reg
= new Regex("Source=\"(.+?)\"");
match
= reg.Match(str);
string sSource = "";
if (match.Groups.Count == 2)
{
sSource
= match.Groups[1].Value;
}
AssemblyPart assemblyPart
= new AssemblyPart();
StreamResourceInfo streamInfo
= App.GetResourceStream(new StreamResourceInfo(packageStream, "application/binary"), new Uri(sSource, UriKind.Relative));
if (sSource == assemblyName)
{
asm
= assemblyPart.Load(streamInfo.Stream);
}
}
return asm;
}

}
}

源代码下载

 

 

      

posted @ 2011-01-27 11:18  焦涛  阅读(1364)  评论(0)    收藏  举报