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/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏WOLFRAM

Mathematica带您一起迎接五一

1854
来自专栏菩提树下的杨过

ExtJs+WCF+LINQ实现分页Grid

上篇文章《用ExtJs+Linq+Wcf打造简单grid 》,这个网格控件不带分页,本文在上文的基础上添加分页功能,文中会着重介绍如何在用LINQ返回分页数据,...

3497
来自专栏高性能服务器开发

(三) 服务器端的程序架构介绍2

下面我们以pc端登录为例来具体看一个数据包在服务器端各个服务之间走过的流程: 步骤1:login_server初始化侦听socket,设置新连接到来的回调函数。...

4044
来自专栏逸鹏说道

逆天通用水印扩展篇~新增剪贴板系列的功能和手动配置,卸除原基础不常用的功能

常用技能:http://www.cnblogs.com/dunitian/p/4822808.html#skill 逆天博客:http://dnt.dkil.n...

28210
来自专栏游戏杂谈

基于SOUI开发一个简单的小工具

Duilib 很久不维护了,而很多不同的分支,似乎都不太维护。微信 Windows 的版本是基于 Duilib 进行开发的,说明应该还是很广泛的。

2973
来自专栏Android开发经验

Volley从源码梳理主要工作流程简记

重点来了。 这里开启了一个缓存调度线程CacheDispatcher,一个网络请求调度线程NetworkDispatcher。

702
来自专栏Petrichor的专栏

tree指令

1802
来自专栏WOLFRAM

by 骁君

1353
来自专栏PPV课数据科学社区

【学习】七天搞定SAS(一):数据的导入、数据结构

SAS的数据类型 ? 首先,sas的编程大概就两块:Data和PROC,这个倒是蛮清晰的划分。然后目前关注data部分。 SAS的数据类型还真的只有两种:数字和...

38812
来自专栏JadePeng的技术博客

使用websocket-sharp来创建c#版本的websocket服务

当前有一个需求,需要网页端调用扫描仪,javascript不具备调用能力,因此需要在机器上提供一个ws服务给前端网页调用扫描仪。而扫描仪有一个c#版本的API,...

7385

扫码关注云+社区

领取腾讯云代金券