The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

WP7 修練 DAY 09:使用巡覽框架的開發技巧與注意事項

在開發以頁面為基礎的 WP7 應用程式時,最重要的就是瞭解所謂的巡覽框架 (Navigation Framework),而這類應用程式其實與 Silverlight 開發時大同小異,但也許還更簡單一些,我們只要瞭解 20% 的重點,就可以應用在 80% 的使用情境上,在此除了介紹一些比較常用的情境外,最後還是會依照我撰寫文章的慣例,列出詳細的相關連結與學習資源供各位參考。

記得我在撰寫【 WP7 修練 DAY 02:如何在頁面顯示前自動轉向到其他頁面 】時曾經在 Page 建構子使用 NavigationService 卻無法執行的問題,如下圖示:

會遇到這個問題,主要還是因為不瞭解頁面生命週期的關係,前陣子在 AppHub 發現一篇非常棒的文章: Windows Phone Silverlight Application Life Cycle,而這篇文章裡有另一張示意圖更加清楚明瞭的指出 WP7 應用程式的執行生命週期,以及每個事件被觸發的順序,我真的愛死這張圖啦!如下圖:

Windows Phone Silverlight Application Life Cycle 這份 19 頁的文件裡,還清清楚楚、明明白白的提到每一個階段的事件「應該」與「不應該」撰寫的程式碼,我認為任何一位英文閱讀程度還行的人,都應該仔細閱讀這份文件,對你絕對有極大幫助。

因此在學習 Navigation Framework 開發技巧之前,首先還是必須先瞭解應用程式生命週期才能事半功倍,以下幾篇是我推薦的文章:

最後我整理一些常用的程式碼片段與說明如下:

1. 切換至不同頁面的基本語法

在 WP7 應用程式裡,一般都會只用「相對連結」來巡覽網頁,所以如下範例在建立 Uri 物件時,都會傳入第二參數為 UriKind.Relative

NavigationService.Navigate(new Uri("/Page1.xaml", UriKind.Relative));

請注意:最早能使用 NavigationService 屬性的事件是在 Page 類別OnNavigatedTo 方法裡。

2011/11/23 補充

除了透過程式碼轉向到另一個頁面外,也有另外一個完全無須定義撰寫程式的方法,只要透過 XAML 的設定即可,以下是設定的方式:

‧先在專案中新增以下兩個組件參考

‧再加上以下兩行命名空間到 XAML 的根元素

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ic="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"

‧最後參考如下 XAML 設定,替控制項定義一個 <i:Interaction.Triggers> 觸發事件,並透過 <ic:NavigateToPageAction> 直接指向事件觸發時直接導向到另一個頁面。

<Button Content="Button" Height="72" Width="160">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <ic:NavigateToPageAction TargetPage="/Page1.xaml"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

 

2. 取得從上頁傳來的查詢字串 (QueryString)

讀取從上頁傳來的 QueryString 應該會從 Page 類別OnNavigatedTo 方法裡來取得,且須要特別注意的地方是:取得鍵值時不能「直接取得」,要先判斷在不在,否則就會發生以下錯誤:

正確的撰寫語法如下:

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
   base.OnNavigatedTo(e);

   if (this.NavigationContext.QueryString.ContainsKey("Name"))
   {
       PageTitle.Text = this.NavigationContext.QueryString["Name"];
   }
}

 

3. 自訂按鈕實作上一頁、下一頁功能

自行實作上一頁、下一頁功能,必須搭配 CanGoBackCanGoForward 屬性,否則會導致 InvalidOperationException 例外發生,如下範例:

private void btnBack_Click(object sender, RoutedEventArgs e)
{
    if (NavigationService.CanGoBack)
    {
        NavigationService.GoBack();
    }
}

private void btnForward_Click(object sender, RoutedEventArgs e)
{
    if (NavigationService.CanGoForward)
    {
        NavigationService.GoForward();
    }
}

2011/11/23 補充:在目前的 Windows Phone 7.1 版本,其 NavigationService.CanGoForward 永遠會回傳 False,所以可以不用寫這段程式碼。不過,日後的 Windows Phone 版本也許會改變這個行為也說不定,留著供參考即可。

 

4. 不要宣告 NavigationService 屬性NavigatingNavigated 事件

如果你想實作 Navigating 事件,應該改用 Page 類別OnNavigatingFrom 方法。
如果你想實作 Navigated 事件,應該改用 Page 類別OnNavigatedFrom 方法。

之所以為有這樣的建議,主要是因為當你實作與註冊這些事件,可能會導致 Page 物件狀態亂掉的情況,舉個例子來說,你註冊了一個事件,進入下一頁,然後再回到上一頁,就有可能導致重複註冊事件,同樣一段 Code 執行兩遍的情況,因此還是建議照著 MSDN 的建議去覆寫 (override) Page 類別OnNavigatingFromOnNavigatedFrom 方法才是王道。

5. 如何清除所有巡覽過的歷史紀錄

還記得我在【WP7 修練 DAY 01:如何設計啟動畫面 (Splash screen) 】文章裡提到的其中一個注意事項嗎?其描述如下:

請注意:這是為了測試方便才這樣寫的,此寫法有 2 個嚴重的缺點:一個是頁面會先讓你看到 MainPage.xaml 然後才會進入到 SplashScreen.xaml 頁面裡;另一個問題是進入該頁面後,若按下手機的上一頁按鈕,又會繼續跳到 SplashScreen.xaml 這頁,這並非常規的設計法則,小朋友請不要亂學。

然而,修練到 巡覽框架 (Navigation Framework) 時讓我學會了,只要能清除所有巡覽過的歷史紀錄,就不用擔心回上一頁之後又再次進入下一頁的情況,我們可以手動將所有巡覽過的歷史紀錄給清除乾淨,就不會讓我們再次進入第一頁了。以下是程式碼範例:

int numOfHistory = NavigationService.BackStack.Count();
for (int i = 0; i < numOfHistory; i++)
{
    NavigationService.RemoveBackEntry();
}

這也代表著,設計啟動畫面又多了一種實作的方法,也就是直接用一個簡單的 MainPage 頁面,設計特殊的啟動畫面或動畫效果,然後在進入下一頁後直接將歷史紀錄 (BackEntry) 給清除,此時就再也不會進入你的啟動畫面了! ^_^

請注意:在 Windows Phone 7 手機裡,應用程式在執行時有個跟一般 Silverlight 應用程式很不一樣的特性,那就是應用程式剛開啟後,如果你按下手機的 Back 硬體按鍵,就會迫使應用程式自動結束。然而,如果你用了這個技巧把巡覽歷史紀錄給清楚乾淨,此時使用者按下手機的 Back 硬體按鍵就會導致應用程式自動結束。這也是我在修練過程中的意外發現!

2011/11/23 補充打個比方說,你先進入 MainPage.xaml 再進入 PageB.xaml,此時按下 Back 鍵預設會回到 MainPage,假設你希望使用者從 MainPage.xaml 進入 PageB 之後不要再回到 MainPage 而是直接關閉應用程式,那麼清除歷史紀錄這方法就可以輕鬆做到這點需求。

 

今日修練總結

Silverlight 應用程式的巡覽框架 (Navigation Framework) 不是一個小主題,要寫的話可以寫很多,但是還好 Windows Phone 7 提供了一個簡化版的巡覽框架 ,你只要知道一些基本觀念,就能夠自由自在的遊走在 XAML 頁面之間。

當然,不免嘮叨的再耳提面命一次,瞭解 WP7 應用程式的執行生命週期極其重要,以下的相關連結記得都要看完、看懂才行。

 

相關連結