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); }