Как реализовать навигацию между страницами в Xamarin.Forms?
В Xamarin.Forms навигация между страницами — это процесс перемещения пользователя от одного экрана приложения (Page) к другому. Фреймворк предоставляет несколько подходов к навигации, в зависимости от используемой архитектуры и типа страниц. Основные механизмы:
-
NavigationPage — стековая (иерархическая) навигация, классический способ.
-
TabbedPage — навигация по вкладкам.
-
FlyoutPage (ранее MasterDetailPage) — навигация через боковое меню.
-
Shell — современный способ с маршрутизацией и интеграцией различных типов страниц.
-
Modal navigation — модальные страницы (всплывающие/изолированные).
1. Навигация через NavigationPage (иерархическая навигация)
NavigationPage — это контейнер, реализующий стековую структуру переходов между страницами. Каждая новая страница добавляется в стек методом PushAsync(), а возврат назад осуществляется с помощью PopAsync().
Создание NavigationPage
MainPage = new NavigationPage(new HomePage());
Переход на новую страницу
await Navigation.PushAsync(new DetailsPage());
Возврат на предыдущую страницу
await Navigation.PopAsync();
Возврат к корневой странице
await Navigation.PopToRootAsync();
Пример кнопки в XAML
<Button Text="Открыть детали" Command="{Binding OpenDetailsCommand}" />
ViewModel
public ICommand OpenDetailsCommand => new Command(async () =>
{
await Application.Current.MainPage.Navigation.PushAsync(new DetailsPage());
});
2. Модальная навигация (Modal Navigation)
Модальные страницы отображаются поверх всего интерфейса, не влияя на стек NavigationPage. Это может быть полезно для экранов входа, предупреждений, диалогов и т.д.
Открытие модальной страницы
await Navigation.PushModalAsync(new LoginPage());
Закрытие модальной страницы
await Navigation.PopModalAsync();
Модальные страницы не добавляются в стек обычной навигации. Они создаются и закрываются независимо.
3. Навигация с TabbedPage (вкладки)
TabbedPage содержит несколько дочерних страниц и позволяет переключаться между ними по вкладкам. Навигация реализуется автоматически при выборе вкладки.
Пример создания TabbedPage
MainPage = new TabbedPage
{
Children =
{
new HomePage { Title = "Домой" },
new ProfilePage { Title = "Профиль" },
new SettingsPage { Title = "Настройки" }
}
};
Выбор вкладки программно
var tabbedPage = Application.Current.MainPage as TabbedPage;
tabbedPage.CurrentPage = tabbedPage.Children\[1\]; // выбрать вторую вкладку
4. Навигация с FlyoutPage (MasterDetailPage)
FlyoutPage (ранее MasterDetailPage) реализует навигацию через боковое меню, которое открывается свайпом или нажатием на иконку.
Пример структуры
public class AppShell : FlyoutPage
{
public AppShell()
{
Flyout = new MenuPage(); // меню
Detail = new NavigationPage(new HomePage()); // содержимое
}
}
Переход на страницу из меню
((FlyoutPage)Application.Current.MainPage).Detail = new NavigationPage(new ProfilePage());
((FlyoutPage)Application.Current.MainPage).IsPresented = false; // закрыть меню
5. Навигация через Shell
Shell — современная и унифицированная система навигации в Xamarin.Forms, доступная начиная с версии 4.0. Позволяет использовать маршруты, вкладки, боковое меню, глубокие ссылки и упрощённый синтаксис переходов между страницами.
Создание AppShell (XAML)
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
x:Class="MyApp.AppShell">
<FlyoutItem Title="Главная">
<ShellContent Route="home" ContentTemplate="{DataTemplate local:HomePage}" />
</FlyoutItem>
<FlyoutItem Title="Профиль">
<ShellContent Route="profile" ContentTemplate="{DataTemplate local:ProfilePage}" />
</FlyoutItem>
</Shell>
Навигация по маршрутам
await Shell.Current.GoToAsync("profile");
С параметрами
await Shell.Current.GoToAsync($"details?id=42");
Регистрация маршрутов в C#
Routing.RegisterRoute("details", typeof(DetailPage));
Переход к странице с маршрутом
await Shell.Current.GoToAsync("details");
6. Навигация с параметрами (Shell + QueryProperty)
Чтобы передать параметры в страницу при навигации в Shell, используется механизм QueryProperty.
Пример приёма параметров в целевой странице
\[QueryProperty(nameof(ItemId), "id")\]
public partial class DetailPage : ContentPage
{
public string ItemId
{
set
{
// Логика по загрузке данных по ID
}
}
public DetailPage()
{
InitializeComponent();
}
}
Навигация с передачей параметров
await Shell.Current.GoToAsync("details?id=123");
7. Навигация с использованием MVVM
В архитектуре MVVM принято выносить навигационную логику из View в ViewModel, используя команды и сервисы.
Создание интерфейса INavigationService
public interface INavigationService
{
Task NavigateToAsync(Page page);
Task NavigateBackAsync();
}
Пример ViewModel с навигацией
public class MainViewModel
{
public ICommand GoToDetailsCommand { get; }
public MainViewModel()
{
GoToDetailsCommand = new Command(async () =>
{
await Application.Current.MainPage.Navigation.PushAsync(new DetailPage());
});
}
}
8. Навигация внутри StackLayout/ScrollView (без перехода между страницами)
Иногда переключение интерфейса происходит без перехода между страницами, а путём скрытия/отображения различных элементов внутри одной страницы.
Пример в XAML:
<StackLayout x:Name="LoginLayout" IsVisible="True">
<Entry Placeholder="Логин" />
<Entry Placeholder="Пароль" />
<Button Text="Войти" Clicked="OnLoginClicked" />
</StackLayout>
<StackLayout x:Name="ProfileLayout" IsVisible="False">
<Label Text="Добро пожаловать!" />
</StackLayout>
И в коде:
private void OnLoginClicked(object sender, EventArgs e)
{
LoginLayout.IsVisible = false;
ProfileLayout.IsVisible = true;
}
9. Работа с Navigation Stack
Получение текущей страницы:
var currentPage = Navigation.NavigationStack.Last();
Просмотр всего стека:
var pages = Navigation.NavigationStack;
Удаление страниц из стека:
Navigation.RemovePage(Navigation.NavigationStack\[1\]);
10. Общие рекомендации
-
Используйте NavigationPage для простых вложенных переходов (например, список → детали).
-
Применяйте Shell для сложных и многоуровневых приложений.
-
Храните навигационную логику в ViewModel через команды или навигационные сервисы.
-
Избегайте хранения состояний в страницах — лучше использовать ViewModel и DI.
-
Для переходов, требующих подтверждения, используйте DisplayAlert и модальные страницы.
-
Навигация между платформами (например, Android и iOS) работает одинаково, если используется общий код Xamarin.Forms.
Система навигации в Xamarin.Forms — мощная и гибкая, позволяющая реализовать как простые переходы между экранами, так и сложную маршрутизированную архитектуру с Shell, вкладками, боковыми меню и глубокими ссылками. Разработчик сам выбирает подход в зависимости от сложности интерфейса и предпочтительной архитектурной модели.