在學習Windows Phone 7開發時,如果你本身對Silverlight或WPF開發有些瞭解的話,Navigation Framework我相信一定是大家
會用到的部分。因此,這一篇是我自己在學習Windows Phone 7 Application開發時,我覺得需要花一些時間去好好搞懂他底層
原理的部分。
首先,Windows Phone 7的Application主要是基於Silverlight Page Model,提供使用者可以導向指定的Page,更換不同的內容,
因此,你可以建立很多個頁面(Page)在同一個架構(Frame)內進行瀏覽。那在Frame與Page二個的運作關係,往下就仔細說明。
在這裡我不得不感謝一直支援我的滷麵網版主,是他讓我提起興趣寫了這麼一篇文章,再次感謝滷麵網,一個非常不錯的wp7開發論壇,後面我也將再次向大家發布幾篇高品質文章,請大家到滷麵上找我吧,呵呵
進入正題:
〉PhoneApplicationFrame與PhoneApplicationPage:
通過過可以瞭解二者之間的關係,它們都是Microsoft.Phone.Controls Namespace裡重要的組件:
(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要特別注意:Navigated、Navigating、NavigationFailed與NavigationStopped,這四個是在進行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載入觸發順序,可以通過來加以說明:
(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交換時,資料的換手與儲存。
當然,你也可以直接把頁面之間要共用的資料內容,變成如的作法:
透過由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裡,也許你會發現這一段代碼:
// Do not add any additional code to this method
private void CompleteInitializePhoneApplication( object sender, NavigationEventArgs e)
{
// Set the root visual to allow the application to render
if (RootVisual != RootFrame)
RootVisual = RootFrame;
// Remove this handler since it is no longer needed
RootFrame.Navigated -= CompleteInitializePhoneApplication;
}
不知道你是否跟我一樣好奇,什麼是RootVisual。
其實在整個運作Application一開始,還沒有真正載入Page或Frame的時候(也就是在程式出現splash screen的時間點),該Application是
沒有主畫面的,因此,可以看到當App.xaml在InitializePhoneApplication()方法時,寫上了下面代碼:
// Do not add any additional code to this method
private void InitializePhoneApplication()
{
if (phoneApplicationInitialized)
return ;
// Create the frame but don't set it as RootVisual yet; this allows the splash
// screen to remain active until the application is ready to render.
RootFrame = new PhoneApplicationFrame();
RootFrame.Navigated += CompleteInitializePhoneApplication;
// Handle navigation failures
RootFrame.NavigationFailed += RootFrame_NavigationFailed;
// Ensure we don't initialize again
phoneApplicationInitialized = true ;
}
在代碼一開始初始化了一組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來保留目前狀態或識
別導向來往二邊的狀態與資訊,進一步控制呈現的資訊內容。
我希望你能喜歡我的文章!如果你有更多想法,請到滷麵網 wp7開發論壇(codewp7.com)問答區聯絡我,我會很高興知道你在想什麼。同時wp7交流QQ群172765887中,也能找到我的身影,感謝大家,也歡迎大家關注我的微薄(www.weibo.com/codewp7)