PROWAREtech
Xamarin: Tutorial - Page 09
Page Navigation
Pages are either modal or modeless. Modal means user interaction is required before continuing. Simply put, modeless is a page that is not modal.
Page navigation appears to use a stack data structure to keep a list of open pages.
Use Navigation.PushModalAsync()
to open a modal page and Navigation.PushAsync()
to open a modeless one.
Use Navigation.PopModalAsync()
and Navigation.PopAsync()
to destroy the current page and goes back to the
previous one.
Example Code
The following code demonstrates the difference between modal and modeless.
<?xml version="1.0" encoding="utf-8"?>
<!--MainPageXaml.xaml-->
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HelloXamarinForms"
x:Class="HelloXamarinForms.MainPageXaml"
Title="Main Page">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness" iOS="20" Android="20, 0, 20, 20" />
</ContentPage.Padding>
<StackLayout>
<Button Text="Open Modal Page" Clicked="ModalPageClicked" />
<Button Text="Open Modeless Page" Clicked="ModelessPageClicked" />
</StackLayout>
</ContentPage>
// MainPageXaml.xaml.cs
using Xamarin.Forms;
namespace HelloXamarinForms
{
public partial class MainPageXaml : ContentPage
{
public MainPageXaml()
{
InitializeComponent();
}
async void ModalPageClicked(object sender, System.EventArgs e)
{
await Navigation.PushModalAsync(new ModalPage());
}
async void ModelessPageClicked(object sender, System.EventArgs e)
{
await Navigation.PushAsync(new ModelessPage());
}
}
}
<?xml version="1.0" encoding="utf-8" ?>
<!--ModelessPage.xaml-->
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HelloXamarinForms"
x:Class="HelloXamarinForms.ModelessPage"
Title="Modeless Page">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness" iOS="20" Android="20, 0, 20, 20" />
</ContentPage.Padding>
<StackLayout>
<Label Text="Modeless Page Label"
VerticalOptions="Center"
HorizontalOptions="Center" />
<Button Text="Back" Clicked="BackClicked" />
</StackLayout>
</ContentPage>
// ModelessPage.xaml.cs
using Xamarin.Forms;
namespace HelloXamarinForms
{
public partial class ModelessPage : ContentPage
{
public ModelessPage()
{
InitializeComponent();
}
async void BackClicked(object sender, System.EventArgs e)
{
await Navigation.PopAsync();
}
}
}
<?xml version="1.0" encoding="utf-8" ?>
<!--ModalPage.xaml-->
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HelloXamarinForms"
x:Class="HelloXamarinForms.ModalPage"
Title="Modal Page">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness" iOS="20" Android="20, 0, 20, 20" />
</ContentPage.Padding>
<StackLayout>
<Label Text="Modal Page Label"
VerticalOptions="Center"
HorizontalOptions="Center" />
<Button Text="Close" Clicked="BackClicked" />
</StackLayout>
</ContentPage>
// ModalPage.xaml.cs
using Xamarin.Forms;
namespace HelloXamarinForms
{
public partial class ModalPage : ContentPage
{
public ModalPage()
{
InitializeComponent();
}
async void BackClicked(object sender, System.EventArgs e)
{
await Navigation.PopModalAsync();
}
}
}
// App.xaml.cs
using Xamarin.Forms;
namespace HelloXamarinForms
{
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new MainPageXaml());
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
}
Screen Shots
These images are of the above code running on Android. The behavior is pretty much identical on iOS with the only difference being that Android has a back button on the device so the user can go back even on modal forms. iOS cannot go back on modal forms unless a back or close button is placed on the form by the programmer.
Some things to remember about modal and modeless pages are:
- You can open a modal page over any page (modeless or modal).
- You cannot open a modeless page over a modal one.
- Modeless pages only work with a
NavigationPage
.
Changing the Navigation Bar
BarBackgroundColor
and BarTextColor
modify the navigation bar at the top of the screen.
// App.xaml.cs
using Xamarin.Forms;
namespace HelloXamarinForms
{
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new MainPageXaml())
{
BarBackgroundColor = Color.Navy,
BarTextColor = Color.White
};
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
}
Also, it is possible to remove the back button on the navigation bar of modeless pages. Here it is done in the XAML.
<?xml version="1.0" encoding="utf-8" ?>
<!--ModelessPage.xaml-->
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HelloXamarinForms"
x:Class="HelloXamarinForms.ModelessPage"
Title="Modeless Page"
NavigationPage.HasBackButton="False">
<!--NavigationPage.HasBackButton="True" is the default-->
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness" iOS="20" Android="20, 0, 20, 20" />
</ContentPage.Padding>
<StackLayout>
<Label Text="Modeless Page Label" VerticalOptions="Center" HorizontalOptions="Center" />
<Button Text="Back" Clicked="BackClicked" />
</StackLayout>
</ContentPage>
Here, it is done in the code-behind file of the XAML form.
// ModelessPage.xaml.cs
using Xamarin.Forms;
namespace HelloXamarinForms
{
public partial class ModelessPage : ContentPage
{
public ModelessPage()
{
InitializeComponent();
NavigationPage.SetHasBackButton(this, false);
}
async void BackClicked(object sender, System.EventArgs e)
{
await Navigation.PopAsync();
}
}
}
SetHasNavigationBar()
is used to eliminate the navigation bar from the page.
// ModelessPage.xaml.cs
using Xamarin.Forms;
namespace HelloXamarinForms
{
public partial class ModelessPage : ContentPage
{
public ModelessPage()
{
InitializeComponent();
NavigationPage.SetHasNavigationBar(this, false);
}
async void BackClicked(object sender, System.EventArgs e)
{
await Navigation.PopAsync();
}
}
}