日期:2014-05-17  浏览次数:21139 次

Windows Phone开发(三)-- 导航原理分析

Windows Phone开发(三)-- 导航原理分析
2011年06月23日
  前两篇文章中,我们的Demo代码都是基于页面切换的,而我们在Silverlight框架下开发的就是以XAML文件为基础的事件驱动程序。也就是说我们的程序会由一个或多个页面作成,这一点和Web程序很相似,所以页面间的切换就很重要。 这一篇文章就来将介绍Windows Phone平台上导航功能。 从Silverlight3开始,提供了内置的导航框架,可以比较轻松的在 Silverlight Page之间进行切换,并且可以和浏览器的前进、后退按钮集成。在Silverlight 3之前的版本,Silverlight没有特定的导航框架,项目中页面之间的切换是通过修改RootVisual布局容器的内容而实现的
  。利用SDK中提供了Frame和Page可以完成导航操纵。其中Frame是导航的框架,Page通过Frame加载显示并实现页面间的导航。
  Windows Phone程序也是基于Sliverlight的Page Model进行导航,同时你也可以使用后退按钮进行后退操纵。WP上核心的导航容器控件为PhoneApplicationFrame,他可以容纳一个PhoneApplicationPage。我们可以创建多个页面,通过Frame来进行导航。  
  
  对于Windows Phone来说,只允许有一个Frame,一个Frame有一下特性: 操作寄宿的Page页面的属性,比如orientation
  指定页面呈现的客户端区域
  为状态栏和程序栏保留空间
  监听obscured和unobscured事件
  而对于Page来说,他会填充满Frame所在的空间。除此之外,程序中还有Status bar和Application Bar,他们都能设置visible 属性;Window Phone也支持屏幕旋转,但是只有在转动设备时才能使之旋转,而不能通过编程的方式实现,因为orientation是只读属性;我们只能通过设置SupportedOrientations来完成;机器的后退按钮可以完成导航中的后退功能,也能关闭键盘,菜单,弹出窗体,同时还能关闭程序。
  关于使用这两个空间导航,参见前两篇文章的例子。定义一个Frame,设置到VisualRoot。在配置文件中设置开始导航的页面。然后通过Frame或者NavigationService来进行导航。参考:Frame and Page Navigation for Windows Phone 我们还是接着上一篇文章程序启动来展开,看看Frame是如何去导航的。 程序启动的的第一步是在App类中,我们创建了一个PhoneApplicationFrame实例。因为PhoneApplicationFrame是继承于Frame的,所以我们先看看Frame构造函数做了什么。 internal Frame() { base.DefaultStyleKey = typeof(Frame); base.Loaded += new RoutedEventHandler(this.Frame_Loaded); this._hostInfo = new HostInfo(); } 构造函数中绑定一个Loaded事件和设置Host信息(如果看过SilverLight的源码,会发现和这的构造函数是有区别的)。接着就看看PhoneApplicationFrame的构造函数 //有删减 public PhoneApplicationFrame() { Action a = null; ShellFrame.Initialize(); base.DefaultStyleKey = typeof(PhoneApplicationFrame); this.Orientation = PageOrientation.PortraitUp; this._visibleRegion = rect; base._navigationService = new NavigationService(this); if (!Frame.IsInDesignMode() && !base._hostInfo.Rehydrated) { if (a == null) { a = delegate { base.Load(); }; } Deployment.Current.Dispatcher.BeginInvoke(a); } if (Current == null) { Current = this; } } 这里面前面一部分是设置界面方向相关的一些内容,然后设置了可见区域,这里被省略了,这些都是上面说的Frame有的特性;接下来的工作很重要定义了一个NavigationService对象,保存在Frame的字段中。我们接着看看这个NavigationService对象构造函数 internal NavigationService(PhoneApplicationFrame nav) { this._navigationPendingLock = new object(); this._cacheRequiredPages = new Dictionary(); PerfUtil.BeginLogMarker(MarkerEvents.TH_INIT_NAVIG ATIONSERVICE, "NavigationService started"); Guard.ArgumentNotNull(nav, "nav"); this._host = nav; HostFrame = nav; HostInfo info = new HostInfo(); this._shellPageManagerCallback = new ShellPageManagerCallback(); this._shellPageManagerCallback.OnCancelRequestEven tHandler = (EventHandler) Delegate.Combine(this._shellPageManagerCallback.On CancelRequestEventHandler, new EventHandler(this.ShellPageManager_OnCancelRequest )); this._shellPageManagerCallback.OnPageStackReactiva tedEventHandler = (EventHandler) Delegate.Combine(this._shellPageManagerCallback.On PageStackReactivatedEventHandler, new EventHandler(this.She llPageManager_OnPageStackReactivated)); this._shellPageManagerCallback.OnResumePageRequest EventHandler = (EventHandler) Delegate.Combine(this._shellPageManagerCallback.On ResumePageRequestEventHandler, new EventHandler(this.ShellP ageManager_OnResumePageRequest)); this._shellPageManagerCallback.OnInvokeReturningEv entHandler = (EventHandler) Delegate.Combine(this._shellPageManagerCallback.On InvokeReturningEventHandler, new EventHandler(this.OnInvoke Returning)); this._shellPageManager = new ShellPageManager(info.LastInstanceId, info.HostWnd, this._shellPageManagerCallback); this._shellPageManager.OnObscurityChangeEventHandl er += new EventHandler(this._host.Sh ellPageManager_OnObscurityChange); this._shellPageManager.OnLockStateChangeEventHandl er += new EventHandler(this._host.Sh ellPageManager_OnLockStateChange); this._shellPageManager.PauseSupported = true; this._quirkShouldNotAllowBackgroundNavigation = QuirksMode.ShouldNotAllowBackgroundNavigation(); this._quirkShould