使用手機APP時,因為螢幕小的關係,一個功能通常都需要切換多個畫面才能處理完整。所以,頁面切換(Navigation)是Xamarin很重要的機制。
NavigationPage
Class物件是用來提供App的頁面切換的機制,每一個頁面是使用後進先出(LIFO)的stack結構。
以下的截圖顯示了在不同的平台上NavigationPage
的幾個主要元件的模樣
當一個頁面切換到另一個頁面時,背後的機制是Push
一個新頁面到navigation stack上。
當返回上一個頁面時,則是由navigation stack上Pop
目前的頁面
頁面切換
Creating the Root Page
navigation stack的第一頁面就是application的root page,其加入方式如以下程式碼
public App ()
{
MainPage = new NavigationPage (new Page1Xaml ());
}
Pushing Pages to the Navigation Stack
如果要切換頁面,則是透過呼叫目前頁面物件的Navigation
屬性的PushAsync
method
async void OnNextPageButtonClicked (object sender, EventArgs e)
{
await Navigation.PushAsync (new Page2Xaml ());
}
上面的Code會建立一個Page2Xaml
的instance,將其加入navigation stack中,並設定它為運作中頁面。
當PushAsync
method被呼叫時,會觸發底下幾個event
- 當下的頁面的
OnDisappearing
method 會被呼叫 - 被加進來的頁面的
OnAppearing
method 會被呼叫 - The
PushAsync
task completes
Popping Pages from the Navigation Stack
如果是要切換回來上一個頁面,可以使用手機上的Back按鈕,畫面上的或是實體按鈕都行。
也可以透過程式碼進行控制
async void OnPreviousPageButtonClicked (object sender, EventArgs e)
{
await Navigation.PopAsync ();
}
這會讓原先的頁面由navigation stack被移除掉,並切換為上一個頁面
當PopAsync
method被呼叫時,會觸發底下幾個event
- 當下的頁面的
OnDisappearing
method 會被呼叫 - 所返回頁面的
OnAppearing
method 會被呼叫 - The
PopAsync
task completes
頁面切換時傳遞資料
有時候會需要再切換頁面時,傳遞資料給目標頁面。這樣的需求,可以透過以下兩種方式來解決。
透過建構式傳遞資料
在目標頁面的建構式中設計參數以接受原頁面所給的資料,如以下程式碼:
public App ()
{
MainPage = new NavigationPage (new MainPage (DateTime.Now.ToString ("u")));
}
這樣MainPage
就可以透過建構式取得資料了
public MainPage (string date)
{
InitializeComponent ();
dateLabel.Text = date;
}
透過BindingContext傳遞資料
另一個方式,是透過設定目標頁面的BindingContext
屬性以傳遞資料,如以下的程式碼:
async void OnNavigateButtonClicked (object sender, EventArgs e)
{
var contact = new Contact {
Name = "Jane Doe",
Age = 30,
Occupation = "Developer",
Country = "USA"
};
var secondPage = new SecondPage ();
secondPage.BindingContext = contact;
await Navigation.PushAsync (secondPage);
}
這樣子帶來的好處是,目標頁面就可以使用Data Binding的方式顯示資料
操作Navigation Stack
除了上述的PushAsync
method 與 PopAsync
method之外,還有兩個method可以讓我們操作Navigation Stack - InsertPageBefore
與 RemovePage
InsertPageBefore
method可以插入一個頁面到現存的某一頁面之前,如下圖所示:
RemovePage
method則可以由Navigation Stack中移除特定的頁面
這些method可以讓頁面切換的控制更自由,例如當登入成功時,可以插入一個新頁面,並Pop原登入畫面,以達成登入成功的使用者體驗。
async void OnLoginButtonClicked (object sender, EventArgs e)
{
...
var isValid = AreCredentialsCorrect (user);
if (isValid) {
App.IsUserLoggedIn = true;
Navigation.InsertPageBefore (new MainPage (), this);
await Navigation.PopAsync ();
} else {
// Login failed
}
}