WP7 - Navigation Framework原理概論

Windows Phone 7 – Navigation Framework原理概論

在學習Windows Phone 7開發時,如果你本身對Silverlight或WPF實作有些了解的話,Navigation Framework我相信一定是大家

會用到的部分。因此,這一篇是我自己在研讀Windows Phone 7 Application開發時,我覺得需要花一些時間去好好搞懂運作

原理的部分。

 

首先,Windows Phone 7的Application主要是基於Silverlight Page Model,提供用戶可以導向指定的Page,更換不同的內容,

因此,你可以建立很多個頁面(Page)在同一個框架(Frame)內進行瀏覽。那在FramePage二個的運作關係,往下就仔細說明。

 

〉PhoneApplicationFrame與PhoneApplicationPage

透過下圖可以了解二者之間的關係,它們都是Microsoft.Phone.Controls Namespace裡重要的元件:

 IC381784[1]

(a) PhoneApplicationFrame (PhoneApplicationFrame Class):

一個WP7 Application會有一個Frame,該Frame專門來控制內部包括的Page、Control與其他的Element

負責控制整個WP Application呈現的方式,例如:Orientation Property、Render的範圍等,更包括Status Bar與ApplicationBar。

以上是MSDN上的說明,PhoneApplicationFrame可以用的功能還包括:

a-1. PhoneApplicationPage之間的資料交換;

a-2. 結合App.xaml控制整個ApplicationPage內的內容與控件

a-3. 控制PhoneApplicationPage的切換

有幾個Events要特別注意:NavigatedNavigatingNavigationFailedNavigationStopped,這四個是在進行Navigate過程時,

當ApplicationPage裡提出Navigate()、GoBack()或GoForward()後,會將控制權移轉至Frame透過四個Event來進行處理。

 

(b) PhoneApplicationPage (PhoneApplicationPage Class):

它實作Page類別,Page類別提供運作Navigation Framework的處理事件與服務。因此,在一些Sample Code看到的Navigate(),

其實都是透過Page類別進行實作,往上拋轉給PhoneApplicationFrame來進行導向的任務。PhoneApplicationPage會在產生一份

Xaml檔時,就被給予一個對應,它內容可以包括所有User Control裡的資料,當然也有:pivot、chart等。另外,針對Orientation

的改變,即透過OrientationChanged該Event來負責。如果你的程式裡針對方向有特別需要,該Event將會協助你處理不少事情。

 

 

上面敘述了關於整個Windows Phone Application運作的基本元素,接下來說明元素之間如何互相導覽與移動,這是在實作

過程裡,我覺得需要被了解的:

 

〉Page導航的重要元素 – Navigation Framework

Windows Phone Applications是由Silverlight Pages所組合而成,為了讓Pages之間可以互相瀏覽與串聯,因此,存在了一個

Navigation Stack」。該Stack透過First in first out的概念儲存了所有瀏覽過程的Page,協助按下Back鍵時回到目標的頁面。

但在此,MSDN上也提到「過度使用Page,將可能造成Application儲存了多餘殘留的Page資訊在navigation stack中,影響應

用程式的效能與可靠性」。

 

針對Page類別處理導航任務,可以透過NavigationService.Navigate()、GoBack()或GoForward()來進行,然而這三個方法對於

Page的影響與運作流程,可以分成五個必要的Event Handler:

〉Loaded (代表每一次頁面載入完成後,觸發的事件。)

〉Unloaded (從目前該頁面要導向另一個頁面時,觸發的事件。)

〉OnNavigatingFrom (透過NavigationService,要從目前頁面離開過程時,觸發該事件。)

〉OnNavigatedFrom(透過NavigationService,要從目前頁面離開後,觸發該事件。)

   OnNavigatingFrom與OnNavigatedFrom二個是先後順序的關係,通常處理事件都會在OnNavigatedFrom裡,這不代表

   你就不能加入在OnNavigatingFrom處理需要任務,只是OnNavigatingFrom故名思義,它是被觸發於當目前頁面不被在

   使用之前,此時,我們可以用於完成一些任務,例如:關閉目前正在播放的動畫等。

〉OnNavigatedTo(透過NavigationService,前往新的頁面時會自動觸發新的頁面的OnNavigatedTo事件。)

 

每一個XAML檔針對Page載入觸發順序,可以透過下圖來加以說明:

圖片2

(a) 從MainPage.xaml要前往SecondPage.xaml時,先觸發了本身的OnNavgatingFrom與OnNavigatedFrom準備結束本頁;

(b) 接著SecondPage.xaml觸發OnNavigationTo事件,準備把本頁要用的資料透過上一頁轉過來;

(c) MainPage.xaml完成NavigateService導向SecondPage.xaml後,觸發Unloaded事件;

(d) 最後SecondPage.xaml觸發Loaded事件開始載入該頁面需要元件與內容;

 

至於二頁資料要傳過去的方法,可以參考該篇的介紹方法:<How to: Perform Page Navigation on Windows Phone>,

它透過NavigateService.Navigate()來傳遞參數在URL中,並且配合新的一頁的OnNavigatedTo()來處理取得的資料。

上面運作的順序,將會影響在處理Page交換時,資料的換手與儲存。

 

當然,你也可以直接把頁面之間要共享的資料內容,變成如下圖的作法:

圖片3

透過由App.xaml集中控管Page之間交換的資料,這樣有一個好處只要透過App.xaml負責處理Application進入

deActive與Actived時要儲存與取得資料的任務。不需要每一個Page都去負責處理Tombstoning造成的影響。

 

另外,在使用Navigate時,我在其他文件裡有看Sample會去對NavigateContext做一些處理與說明,那最後就來看看它是什麼:

〉Page.NavigationContext

專門處理Navigation請求的內容,上述提及的透過Url傳送參數的方法,就是把要傳遞的內容放置於該NavigationContext類別中。

透過QueryString屬性來取得參數值。

 

====

以上是介紹WP7運作配合Navigation Framework的運用,這一篇其實蠻多基本的原理,撰寫出來是為了讓自己能夠

更清楚他們運作原理的規則,才不會一直在開發上遇到一些根本的問題,而花費不少時間去走冤枉路。

實作WP7程式也有些時日,其實在整個開發過程裡,遇到蠻多原理性的問題。由於我本身對Silverlight原理沒有太深固的基礎,

因此,很常會遇到不太明白為何畫面沒有辦法正常出現或是導向失敗,甚至連要如何透過Back離開自己開發的App也不明白。

這樣的開發經驗,其實讓我感觸深刻,特別將在學習整個Silverlight與WP7上實作的心得,透過該篇文章撰寫必懂的一些概念。

 

[補充]

〉WP7換頁時的作法比較 – PhoneApplicationPage.Content與PhoneApplicationPage.NavigationService

(a) 使用Content來進行換頁,其實原有的Page仍然存在,只是內容被轉換成了新的一個畫面,這樣原先存在

     Page中的內容,將會被覆蓋掉。按下Back鍵時,其畫面不會回到上一個,而一直存在相同的頁面。        

(b) 使用NavigationService來換頁,實際上是將Frame目前控件的Page指定另一個新的Page,原有的Page內容也會被

     保留下來。按下Back鍵時,就可以回到上一個Page。注意的是,Back鍵回去的Page是剛才被產生的instance,

     它並不是一個全新的Page。

 

〉PhoneApplicationFrame與RootVisual

打開App.xaml.cs裡,也許你會發現這一段程式碼:

   1: // Do not add any additional code to this method
   2: private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
   3: {
   4:     // Set the root visual to allow the application to render
   5:     if (RootVisual != RootFrame)
   6:         RootVisual = RootFrame;
   7:  
   8:     // Remove this handler since it is no longer needed
   9:     RootFrame.Navigated -= CompleteInitializePhoneApplication;
  10: }

不知道你是否跟我一樣好奇,什麼是RootVisual

其實在整個運作Application一開始,還沒有真正載入Page或Frame的時候(也就是在程式出現splash screen的時間點),該Application是

沒有主畫面的,因此,可以看到當App.xaml在InitializePhoneApplication()方法時,寫上了下面程式碼:

   1: // Do not add any additional code to this method
   2: private void InitializePhoneApplication()
   3: {
   4:     if (phoneApplicationInitialized)
   5:         return;
   6:  
   7:     // Create the frame but don't set it as RootVisual yet; this allows the splash
   8:     // screen to remain active until the application is ready to render.
   9:     RootFrame = new PhoneApplicationFrame();
  10:     RootFrame.Navigated += CompleteInitializePhoneApplication;
  11:  
  12:     // Handle navigation failures
  13:     RootFrame.NavigationFailed += RootFrame_NavigationFailed;
  14:  
  15:     // Ensure we don't initialize again
  16:     phoneApplicationInitialized = true;
  17: }

在程式一開始初始化了一組RootFrame(也就是PhoneApplicationFrame),並且在RootFrame完成Navigated事件處理時,即呼叫

CompleteInitializePhoneApplication()事件處理者,該事件處理者就把RootFrame指定給RootVisual,讓應用程式得知主畫面是誰。

然而,Frame成為了主畫面,而PhoneApplicationPage只是Frame中的Content。

換句話說,RootVisual就是用來取得或設定主要應用程式的UI。所以我們才可以透過Frame來控制所有的Page。但是,

它有一個先天的條件:「您只能從程式碼設定 RootVisual 屬性值一次,但是可不限次數地取得其值。」這點要特別注意。

 

〉離開WP7程式

雖然說這個標題不是什麼太新鮮的話題了,但想大家都知道要從自己程式離開的話,直接透過丟出一個Exception來自訂處理,

就可以離開自己的程式了,但也還有其他的方式。那就是透過「Microsoft.XNA.Game」這個Namespace,直接使用Game類別提供

的”Exit()”方法來離開。大家可以試看看。

 

 

 

〉Application Page Model of Windows Phone:

Application Page Model是WP7整個運作的關鍵,它與該篇介紹的Navigation Framework是互相關聯的,因此,如果這篇內容,

有寫的不夠詳細的地方,可以直接往Application Page Model這個關鍵字下去搜尋。另外,順帶一提,在MSDN文件裡有看到

Page與Screen的定義,二者的差別在於:

  Page Screen
  A user-recognizable collection of persistent state. not a user-recognizable collection of persistent state
  as a Silverlight page that contains information, memorable content, or links to other pages. such as a pop-up window, dialog box, or splash screen.

 

〉擷取MSDN上針對Navigation使用的建議:

A. Screens and Non-Navigational Transitions

    針對transient UI(短暫出現的UI),建議使用Pop-Up Control去呈現內容。實作BackKeyPress事件去隱藏PopUp(或Dialog box)的內容。

B. Multiple Content Views

    對於使用多個頁面顯示內容,建議可以使用多個DataContext元件來透過與用戶的操作進行資料的互動與呈現。當然,你可以使用

    多個Page來實作會比較容易,但必須注意Back鍵的處理以免造成多餘的stack資訊被儲存下來。

C. Saving State and Tombstoning

    建議注意程式儲存目前狀態的處理,由於程式可能被轉換成tombstone,因此,可以透過NavigationContext API來保留目前狀態或識

    別導向來往二邊的狀態與資訊,進一步控制呈現的資訊內容。  

 

References:

WP7 Navigation in depth | Navigation Framework  & Frame and Page Navigation Overview for Windows Phone (必讀)

How to: Perform Page Navigation on Windows Phone & Exercise 1: Introduction to Navigation in Windows Phone

WP7 Developer Blog : 解决WP7应用中循坏导航的问题 & Solving Circular Navigation in Windows Phone Silverlight Applications

Back-Chaining in WP7

Exit from Silverlight WP7 Application & How to Quit a WP7 Silverlight Application

.NET Framework 4 - NavigationService 類別

Silverlight for windows phone 7 Application life cycle & Navigation

Removing a page from the navigation stack

Windows Phone 7 Quick Tip #3 – Use a NavDictionary to pass state between pages (必讀)

WP7 Development Tip of the Day: Navigating between pages: NavigateUri vs. NavigationService (必讀)

Redirecting an initial navigation

Introducing the concept of “Places”

 

Dotblogs 的標籤: ,