Windows Phone 7 - 頁面間傳值 分類: Windows Phone 7 2011-01-23 20:42 441人閱讀 評論(0) 收藏 舉報
在頁面間導航時傳遞參數的方式大致有3種,QueryString,全域變數和隔離儲存區 (Isolated Storage)。本文只介紹前兩種傳值方式。
一.QueryString方式
在頁面1中的Button事件處理常式中添加了如下代碼:
[c-sharp] view plaincopy
- private void btnMain_Click(object sender, RoutedEventArgs e)
- {
- string target = "/SubPage.xaml";
- target += string.Format("?InputText={0}", txtInput.Text);
- this.NavigationService.Navigate(new Uri(target, UriKind.Relative));
- }
程式運行時這個Uri是這樣的:”/SubPage.xaml?InputText=Hello, Windows Phone 7!” 它的形式和HTML中的查詢字串
(Query String)一樣,如果要傳遞多個參數,可以用&來合并,例如:
”/SubPage.xaml?InputText=Hello, Windows Phone 7!&Name=Zhang Yin”。頁面2中Button的Click事件處理常式代碼如下:
[c-sharp] view plaincopy
- private void btnBack_Click(object sender, RoutedEventArgs e)
- {
- if (this.NavigationService.CanGoBack)
- this.NavigationService.GoBack();
- }
並且我在頁面2中重寫了OnNavigatedTo方法。OnNavigatedTo方法是定義在Page類中的,
所以PhoneApplicationPage也繼承了此方法,它是一個Virtual方法,所以需要用override關鍵字重寫。
OnNavigatedTo在頁面被建立後馬上會被調用,也就是說在OnNavigatedTo 方法被調用時,頁面的建構函式已經執行完畢了。
類似的還有OnNavigatedFrom方法,它是在離開當前頁面時觸發的。頁面2中OnNavigatedTo方法內的代碼如下:
[c-sharp] view plaincopy
- protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
- {
- string value = string.Empty;
- IDictionary<string, string> queryString = this.NavigationContext.QueryString;
- if (queryString.ContainsKey("InputText"))
- {
- txt.Text = queryString["InputText"];
- }
- base.OnNavigatedTo(e);
- }
Page類定義了一個類型為NavigationContext的NavigationContext屬性,它包含一個類型為IDictionary<string, string>的
QueryString屬性。判空檢測後,將InputText鍵對應的值賦給文字框的Text屬性。
最後觸發基類的OnNavigatedTo方法以保證基類的功能正常。當然也可以使用下面的代碼,效果是一樣的:
[c-sharp] view plaincopy
- protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
- {
- string value = string.Empty;
- IDictionary<string, string> queryString = this.NavigationContext.QueryString;
- queryString.TryGetValue("InputText", out value);
- if (value != null)
- {
- txt.Text = value;
- }
- base.OnNavigatedTo(e);
- }
通過QueryString雖然可以向一個頁面傳遞參數,但卻無法回傳資料,例如我在頁面2中將文本修改為“Windows Phone 7!”,
然後點擊“前往第1頁”按鈕,得到的還是初始的那個頁面。要解決這個問題,就需要使用全域變數了。
二.全域變數
對於全域變數來說,我們可以在項目中添加一個在整個程式生命週期中都能訪問到的類,將相應的資料儲存在這個類的屬性裡。
不過現在我們不用自己動手做這些額外的工作了。項目中本身就有一個類滿足這個需求:App類。 App 類繼承自Application類。
通過Application的Current屬性就可以擷取到與當前程式關聯的Application類執行個體,然後通 過轉換就可以得到App類執行個體。
程式中所有的頁面都可以訪問到這個App類,所以將我們要儲存的資料放到App類中是最好不過了,免去了自己實現的麻煩。
在App類中添加一個公有的InputText屬性(C# 3.0的自動屬性) :
[c-sharp] view plaincopy
- public partial class App : Application
- {
- public string InputText { get; set; }
- ……
- }
頁面1中的代碼如下:
[c-sharp] view plaincopy
- protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
- {
- App app = Application.Current as App;
- if (app.InputText != null)
- txtPage1.Text = app.InputText;
- base.OnNavigatedTo(e);
- }
-
- protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
- {
- App app = Application.Current as App;
- app.InputText = txtPage1.Text;
- base.OnNavigatedFrom(e);
- }
我在OnNavigatedTo方法內,讀取App類的InputText值,為的是當在頁面2中修改了文本後可以反映到頁面1中。
注意:OnNavigatedTo方法是在當前頁面被啟用(成為活動頁面)時調用的。
在OnNavigatedFrom方法中將文字框賦給App類的InputText屬性,供頁面2去讀取。
頁面2中的代碼如下:
[c-sharp] view plaincopy
- protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
- {
- App app = Application.Current as App;
- if (app.InputText != null)
- txtPage2.Text = app.InputText;
- base.OnNavigatedTo(e);
- }
-
- protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
- {
- App app = Application.Current as App;
- app.InputText = txtPage2.Text;
- base.OnNavigatedFrom(e);
- }
頁面2中的操作與頁面1類似。這樣,當我們再次將頁面2中的文本修改為“Windows Phone 7!”,然後點擊“前往第1頁”按鈕時,
就可以得到想要的結果了。
三.PhoneApplicationService類
類似於App類,我們還可以將要在多個頁面中訪問的資料儲存在PhoneApplicationService的State屬性中。
它的類型是IDictionary<string, object>,所以我們可以儲存任意對象,不過前提是這個對象是可序列化的(serializable)。
在程式中,我們無需自己建立的執行個體,通過PhoneApplicationService的靜態屬性Current就可以擷取到已有的執行個體。
注意:在程式中訪問PhoneApplicationService類需要添加下面的名稱空間:
using Microsoft.Phone.Shell;
程式碼如下,頁面1中的代碼如下:
[c-sharp] view plaincopy
- protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
- {
- if (PhoneApplicationService.Current.State.ContainsKey("InputText"))
- {
- txtPage1.Text = PhoneApplicationService.Current.State["InputText"] as string;
- }
- base.OnNavigatedTo(e);
- }
-
- protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
- {
- PhoneApplicationService.Current.State["InputText"] = txtPage1.Text;
- base.OnNavigatedFrom(e);
- }
頁面2中的代碼如下:
[c-sharp] view plaincopy
- protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
- {
- if (PhoneApplicationService.Current.State.ContainsKey("InputText"))
- {
- txtPage2.Text = PhoneApplicationService.Current.State["InputText"] as string;
- }
- base.OnNavigatedTo(e);
- }
-
- protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
- {
- PhoneApplicationService.Current.State["InputText"] = txtPage2.Text;
- base.OnNavigatedFrom(e);
- }
四.關於OnNavigatedTo和OnNavigatedFrom方法
我覺得這兩個方法的名字起的不太好,有時候容易混淆,如果把OnNavigatedTo改為OnNavigatedToThisPageFromOther,
把OnNavigatedFrom改為OnNavigatedFromThisPageToOther就會很清晰了,當然這隻是協助我們記憶的一種方法了。
下面是MSDN中對這兩個方法的一些建議:
OnNavigatedTo:重寫 OnNavigatedTo 方法以檢查導航請求並且準備供顯示的頁面。
例如,可以載入請求的資料並且啟用或禁用可視化元素。通常是使用 OnNavigatedTo 方法,而非為 Loaded 事件建立事件處理常式。
最好使用 OnNavigatedTo 方法,因為只在每次頁面成為活動頁面時調用該方法一次。
Silverlight 架構在每次將元素添加到視覺化樹狀結構時引發 Loaded 事件,在啟用某一頁面時該事件可能會多次發生。
OnNavigatedFrom:重寫 OnNavigatedFrom 方法以便在頁面成為非活動時對該頁面執行最後的操作。
例如,可以更新與該頁面相關的資料。通常是使用 OnNavigatedFrom 方法,而非為 Navigated 事件建立事件處理常式。
最好使用 OnNavigatedFrom 方法,因為不必再從 NavigationService 對象移除事件處理常式以避免物件存留期問題。