Windows Phone 8.1 新特性 - 页面导航

本篇介绍一下Windows Phone 8.1 中页面导航的实现方式。

大家对Windows Phone 8 中页面导航的实现一定不陌生,我们使用 NavigationService 来实现。具体写法是这样的:

NavigationService.Navigate(new Uri("XAML相对路径", UriKind.RelativeOrAbsolute));

而在导航目标页,我们在 OnNavigatedTo 方法中通过 NavigationContext.QueryString["key"] 来接收页面传递的参数。

当按下回退键时,导航源页面会被从回退栈中取出显示,这样我们就完成了一个完整的页面导航过程。

而在Windows Phone 8.1 中,导航方式有所不同,首先我们需要在导航源页面做如下处理:

Frame.Navigate(typeof(NavigationDemoPage), null);

我们利用到了Page内容控制Frame的Navigate方法,它有两个参数,第一个参数是导航目标页的类型,第二个参数(可选)为页面间传递的参数。

而在目标页,我们通过 NavigationHelper 来完成接受参数和其他处理。当我们在项目中新建一个基本页(BasicPage)时,Common文件夹中会出现NavigationHelper类和其他一些辅助类。

NavigationHelper 有两个很重要的事件 LoadState 和 SaveState,分别用来加载已保存状态和保存当前页的状态。而接收导航参数就会用到LoadState 事件,来看看我们在它的注册方法中的处理:

private void NavigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
    var param = e.NavigationParameter;
}

与Windows Phone 8中可传递多个字符串参数不同的是,8.1 中导航参数只有一个,而且是object 类型,这也就是说我们可以传递包括字符串在内的很多自定义类型,这在参数传递和使用上无疑方便了很多。

在按下回退键时,页面返回到导航源。而如果我们没有使用NavigationHelper 的话,页面是没有办法正常回退的,这是怎么回事呢,我们来看看NavigationHelper 的构造函数吧:

        public NavigationHelper(Page page)
        {
            this.Page = page;

            // 当此页是可视化树的一部分时,进行两个更改: 
            // 1) 将应用程序视图状态映射到页的可视状态
            // 2) Handle hardware navigation requests
            this.Page.Loaded += (sender, e) =>
            {
#if WINDOWS_PHONE_APP
                Windows.Phone.UI.Input.HardwareButtons.BackPressed += HardwareButtons_BackPressed;
#else
                // 仅当占用整个窗口时,键盘和鼠标导航才适用
                if (this.Page.ActualHeight == Window.Current.Bounds.Height &&
                    this.Page.ActualWidth == Window.Current.Bounds.Width)
                {
                    // 直接侦听窗口,因此无需焦点
                    Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated +=
                        CoreDispatcher_AcceleratorKeyActivated;
                    Window.Current.CoreWindow.PointerPressed +=
                        this.CoreWindow_PointerPressed;
                }
#endif
            };

            // 当页不再可见时,撤消相同更改
            this.Page.Unloaded += (sender, e) =>
            {
#if WINDOWS_PHONE_APP
                Windows.Phone.UI.Input.HardwareButtons.BackPressed -= HardwareButtons_BackPressed;
#else
                Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated -=
                    CoreDispatcher_AcceleratorKeyActivated;
                Window.Current.CoreWindow.PointerPressed -=
                    this.CoreWindow_PointerPressed;
#endif
            };
        }

我们看到,这是有一个条件编译符 WINDOWS_PHONE_APP。在使用了NavigationHelper 的Page 中,Loaded 和 UnLoaded 事件处理代码中都加入了Windows.Phone.UI.Input.HardwareButtons.BackPressed 的处理,这就是对硬件回退按钮点击的响应,响应事件如下:

        private void HardwareButtons_BackPressed(object sender, Windows.Phone.UI.Input.BackPressedEventArgs e)
        {
            if (this.GoBackCommand.CanExecute(null))
            {
                e.Handled = true;
                this.GoBackCommand.Execute(null);
            }
        }
        public RelayCommand GoBackCommand
        {
            get
            {
                if (_goBackCommand == null)
                {
                    _goBackCommand = new RelayCommand(
                        () => this.GoBack(),
                        () => this.CanGoBack());
                }
                return _goBackCommand;
            }
            set
            {
                _goBackCommand = value;
            }
        }

我们看到,事件的处理中执行了GoBackCommand 来导航到导航历史中的最新项。

最有还有一点要说明,Windows Phone 8.1 中,页面导航回退时,导航源页面会重新Load,对于需要加载数据等的页面,这种重新加载的结果并不是我们想看到的。

这里我们可以使用 NavigationCacheMode 来避免这一现象,我们在页面构造方法中对它进行设置,它是一个枚举类型,有三种枚举值:

  • Disabled 不缓存页面,导航返回时重新加载页面
  • Required 缓存页面,且不考虑缓存大小
  • Enabled 缓存页面,但是当超过缓存大小的限制时,放弃缓存。

好了,到这里我们就把Windows Phone 8.1 中的页面导航相关知识介绍完了,希望对大家有帮助,谢谢。

 

posted @ 2014-04-21 11:34  shaomeng  阅读(2843)  评论(6编辑  收藏  举报