Silverlight的导航框架与动态加载

1. Silverlight 3 的导航框架简介

Silverlight 提供了内置的导航框架,可以比较轻松的在 Silverlight Page 之间进行切换,并且可以和浏览器的前进、后退按钮集成,下面的代码可以简单的说明其用法:

image

这段代码很简单,通过设置 HyperLinkButton 的 NavigationUri 和 TargetName 两个属性,可以让指定的 Frame 去加载指定的 Silverlight Page 。

2. 常见的动态加载解决方案

当 Silverlight 项目比较大的时候, 很自然的会想到将 Silverlight 项目拆分成多个 xap 文件,进行按需加载,这个实现起来也不难。通常的做法是使用 WebClient 或者 HttpWebRequest ,向服务端请求所需的 xap 文件,然后通过 xap 压缩包内的 AppManifest.xaml 文件,获取到 xap 文件内部打包的 dll 文件信息,在客户端通过反射进行加载。

3. 导航框架与动态加载相结合时遇到的问题,原因与解决方法

如 果将这两者结合起来,利用 Sliverlight 内置的导航框架来加载动态加载的 xap 文件内部的 Silverlight Page ,对应用程序的开发和用户体验都是有很大帮助的:对开发方面来说,不用反射加载,而是使用 Silverlight 内置的导航框架,可以节省很多代码;对用户体验方面,按需加载能减少初始加载文件的大小,减少等待时间,使用导航框架可以和浏览器的前进、后退按钮紧密集 成,用户体验更佳。

但是,在 Silverlight 3 目前的版本中, Frame 控件似乎不能直接加载动态加载的 Silverlight Page , 不管是通过设置 HyperLinkButton 的 NavigateUri 属性,还是通过调用 Frame.Navigate(Uri source) 方法,都会出现相同的异常, 看下面代码:

var xap = "http://localhost:2704/AppSL.Web/ClientBin/TestSLApp.xap";
// LoadPackage 是加载 xap 的扩展方法
Deployment.Current.LoadPackage(xap, () => {
var uri = new Uri("/TestSLApp;component/MainPage.xaml", UriKind.Relative);
this.WidgetFrame.Navigate(uri);
});

当执行至 WidgetFrame.Navigate(uri) 时,会出现下面的异常:

image

是什么原因导致这个异常呢? 通过 Reflector 察看 PageResourceContentLoader ,发现加载 x:Class 的是这个 GetTypeFromAnyLoadedAssembly 方法:

image 

这个方法只是遍历 Deployment.Current.Part 去寻找所需要的类型,并没有去遍历动态加载的文件, 当然,这里也不可能去遍历。

看到这里,终于找到异常出现的原因了,由于这个方法是私有并且是静态的,无法进行重写,只能通过其它途径来解决。我想到的解决方法是,新建一个 Silverlight Page, 然后删除对应的代码文件,删除 xaml 视图的 x:Code 信息,如下图所示:

image

最后的解决方案就是, 要做一个引导的文件,这个文件必须是一个独立的 xaml 文件,没有代码文件,没有 x:Class 信息,这样就不会被编译成新的类型,自然可以被 Silverlight 的导航框架加载了。

最后说一句,不知道 Silverlight 以后的版本会不会考虑动态加载的问题呢? 据我所知, Flex 已经内置了模块动态加载的机制了。

共有0个回答