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();
		}
	}
}
<< < [Page 9 of 11] > >>