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

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

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

 

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

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

Xaml :

代码
<UserControl x:Class="LoadXap.MainPage"
    xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d
="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable
="d" d:DesignWidth="640" d:DesignHeight="480">
  
<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>
</UserControl>

CS代码:

代码
using System;
using System.IO;
using System.Net;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Resources;
using System.Xml;

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;
        }
    }
}

演示效果:http://images.24city.com/jimmy/loadXap/




posted @ 2009-12-22 17:28  菩提树下的杨过  阅读(3425)  评论(11编辑  收藏  举报