Windows Phone 8.1 页面导航
1. Windows Phone 8.1 的应用框架
一个应用拥有 1 个 Window,一个 Window 包含 1 个 Frame,一个 Frame 包含 多个 Page。
获取 Frame 的方法为:
Frame rootFrame = Window.Current.Content as Frame;
用 Page 填充 Frame 的方法为:
rootFrame.Navigate(typeof(MainPage))
2. Windows Phone 8.1 与 Windows Phone 8.0 导航的不同
(1)“返回键”的默认行为是返回到上一个应用(没有上一个应用则返回桌面),并不是上一个页面。
若想要实现返回上一个页面的操作,则需要改写 HardwareButtons.BackPressed 事件:
public App() { this.InitializeComponent(); this.Suspending += this.OnSuspending; HardwareButtons.BackPressed += HardwareButtons_BackPressed; } private void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e) { Frame rootFrame = Window.Current.Content as Frame; if( rootFrame != null && rootFrame.CanGoBack ) { rootFrame.GoBack(); e.Handled = true; } }
或者只对某个 Page 改写:
protected override void OnNavigatedTo(NavigationEventArgs e) { HardwareButtons.BackPressed += HardwareButtons_BackPressed; } private void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e) { e.Handled = true; if( Frame.CanGoBack ) Frame.GoBack(); } protected override void OnNavigatedFrom(NavigationEventArgs e) { HardwareButtons.BackPressed -= HardwareButtons_BackPressed; }
(2)导航方法改为 Frame.Navigate。
导航时不再需要填写下一个页面的 Uri,而是直接使用页面的类型,并且可以直接将 Object 传递到下一个页面:
Frame.Navigate(typeof(Page2), "From MagePage.");
当然,这就需要下一个页面对传递过来的 Object 进行拆箱:
protected override void OnNavigatedTo(NavigationEventArgs e) { myTextBlock.Text = (string)e.Parameter; }
3. Frame.BackStack
应用可以获取之前的导航历史记录(不包括当前页面),Frame.BackStack 返回的是 IList<PageStackEntry>:
List<string> backStack = new List<string>(); foreach( var item in Frame.BackStack ) { backStack.Add(item.SourcePageType.Name); } myListView.ItemsSource = backStack;
可以轻松移除导航历史中的某项:
var backStack = Frame.BackStack; backStack.RemoveAt(Frame.BackStackDepth - 1); if( Frame.CanGoBack ) Frame.GoBack();
4. NavigationCacheMode
应用默认不对页面进行缓存,若要缓存当前页面则可以设置页面 NavigationCacheMode 属性:
public MainPage() { this.InitializeComponent(); this.NavigationCacheMode = NavigationCacheMode.Required; }
同样可以更改 App.xaml.cs 里 OnLaunched 方法的 CacheSize:
protected override void OnLaunched(LaunchActivatedEventArgs e) { Frame rootFrame = Window.Current.Content as Frame; if( rootFrame == null ) { rootFrame = new Frame(); // TODO: 将此值更改为适合您的应用程序的缓存大小 rootFrame.CacheSize = 1; if( e.PreviousExecutionState == ApplicationExecutionState.Terminated ) { } Window.Current.Content = rootFrame; } if( rootFrame.Content == null ) { if( rootFrame.ContentTransitions != null ) { this.transitions = new TransitionCollection(); foreach( var c in rootFrame.ContentTransitions ) { this.transitions.Add(c); } } rootFrame.ContentTransitions = null; rootFrame.Navigated += this.RootFrame_FirstNavigated; if( !rootFrame.Navigate(typeof(MainPage), e.Arguments) ) { throw new Exception("Failed to create initial page"); } } Window.Current.Activate(); }
5. NavigationHelper
如果你新建的项目不是空白项目,则会在项目中发现一个 Common 文件夹,而该文件夹中会有一个 NavigationHelper 类。
该类会帮你解决应用的导航问题,使用方法:
(1) 在某处创建一个 NavigationHelper 实例(如页面的构造函数中),并注册 LoadState 和 SaveState 事件的回调。
public MyPage() { this.InitializeComponent(); var navigationHelper = new NavigationHelper(this); this.navigationHelper.LoadState += navigationHelper_LoadState; this.navigationHelper.SaveState += navigationHelper_SaveState; } private async void navigationHelper_LoadState(object sender, LoadStateEventArgs e) { } private async void navigationHelper_SaveState(object sender, LoadStateEventArgs e) { }
(2) 在以下情况下注册页面以调入 NavigationHelper: 该页面通过重写 OnNavigatedTo 和 OnNavigatedFrom 事件以参与导航:
protected override void OnNavigatedTo(NavigationEventArgs e) { navigationHelper.OnNavigatedTo(e); } protected override void OnNavigatedFrom(NavigationEventArgs e) { navigationHelper.OnNavigatedFrom(e); }