第3章页面导航
通过上一章的学习,读者已经了解到应用程序的基本结构,以及如何对应用程序生命周期内各个阶段进行处理,本章将向读者讲述与页面导航相关的内容。
与网站应用程序相似,UAP应用程序也会划分为多个页面,不同的页面将向用户呈现不同的内容。例如,一个闹钟应用程序可能存在以下页面: 浏览页面用于列出用户已经创建的闹钟清单以及每条闹钟信息的状态; 编辑页面可用于填写新闹钟信息或修改现有闹钟的信息; 设置页面允许用户对应用程序进行个性化选择,如自定义闹钟铃声等。
可见,合理使用页面导航,能够增强应用程序的层次性和逻辑表现能力。本章内容包括:
使用Frame类实现页面导航;
导航并传递参数;
管理导航记录;
处理手机上的“回退”按钮事件;
理解页面缓存;
管理页面的导航状态。
3.1实现导航
Frame类派生自ContentControl类,这说明它是一个内容控件。与其他内容控件不同的是,Frame具有导航功能,因此,Frame类的内容属性所承载的通常是应用程序页面的实例,而实现页面导航是通过调用Navigate方法来完成的,该方法有多个重载,比较常用的有以下两个重载版本:
public bool Navigate(System.Type sourcePageType);
public bool Navigate(System.Type sourcePageType, object parameter);
其中,sourcePageType参数是必须的,类型为Type,即要导航的目标页面的类型。第二个重载版本有一个parameter参数,可为任意类型,表示导航参数,也就是在导航到目标页面时传递的附加信息,目标页面可以根据parameter参数来做出相应处理,本章后面会向读者详细说明。
每个应用程序页面由Page类表示,但通常不会直接使用Page类,在向应用程序项目添加新页面时都会从Page类派生出一个子类,即自定义页面类,Navigate方法中的sourcePageType参数则指定为自定义页面类的Type。如果导航顺利完成,Navigate方法返回True,否则返回False。如果导航失败,会引发NavigationFailed事件。
下面示例将演示如何通过Frame对象来实现页面导航。
应用程序项目包含两个页面: FirstPage和SecondPage。应用程序运行后将导航到FirstPage页,接着在FirstPage页上单击页面下方的命令按钮进入SecondPage页。
首先将App类的代码做如下修改:
public sealed partial class App : Application
{
public App ()
{
this.InitializeComponent();
}
///
/// 用于导航的Frame对象
///
public Frame RootFrame { get; private set; }
protected override void OnLaunched ( LaunchActivatedEventArgs args )
{
// 实例化Frame对象
RootFrame = new Frame();
// 将当前Frame作为窗口的内容
Window.Current.Content = RootFrame;
// 导航到页面一
RootFrame.Navigate(typeof(FirstPage));
// 激活当前窗口
Window.Current.Activate();
}
}
代码先实例化一个Frame对象,然后将它作为当前窗口的内容,紧接着调用Navigate方法导航到FirstPage页。
在FirstPage中,通过处理命令按钮事件导航到SecondPage页,代码如下:
private void OnNext ( object sender, RoutedEventArgs e )
{
this.Frame.Navigate(typeof(SecondPage));
}
由于Page类公开了一个Frame属性,可以获取负责导航的Frame实例的引用,因此上面代码通过Frame属性得到参与导航的Frame对象,然后调用其Navigate方法导航到SecondPage页。
应用程序的运行结果如图31所示。
图31使用Frame类进行页面导航
完整的示例代码请参考\第3章\Example_1。
3.2导航事件
在页面导航过程中,应用程序会引发一系列事件,在需要的时候,开发者应该处理这些事件。
对Frame而言,在导航到目标页面之前会引发Navigating事件,此时可以做必要的检查,如果希望取消导航,可以设置事件参数NavigatingCancelEventArgs的Cancel属性为True来阻止导航; 当Frame对象顺利导航到目标页面后,会发生Navigated事件。通过事件参数对象的SourcePageType属性可以获得目标页面的类型,即传递给Navigate方法的sourcePageType参数的值。
对于页面来说,当导航进入页面后,会调用OnNavigatedTo方法; 当导航即将离开页面时,OnNavigatingFrom方法会被调用,同样,可以通过设置方法参数e的Cancel属性为True来取消导航; 当导航已经离开当前页面后会调用OnNavigatedFrom方法。以上三个方法都是虚方法,开发者在派生类中可以重写它们并加入自定义处理代码。
那么,如何知道上面所述的几个事件的发生顺序呢?接下来将通过一个示例来向读者展示各个导航事件的引发顺序。
在应用程序项目中添加三个页面,分别命名为Page1、Page2和Page3。三个页面的结构相似,所以此处只介绍Page1页面的结构,其描述界面布局的XAML代码如下:
VerticalAlignment="Center"
HorizontalAlignment="Center"/>
页面中仅用一个TextBlock元素来显示标识文本,以方便在运行阶段进行观察。
本示例程序主窗口的内容对象并非Frame实例,而是MainPage页面,然后将负责导航的Frame对象放置在MainPage页面中。MainPage页面的XAML如下:
Page 1
Page 2
Page 3
Navigating="OnFrameNavigating"
Navigated="OnFrameNavigated">
……