Область
Совет
Это содержимое является фрагментом из электронной книги, шаблонов корпоративных приложений с помощью .NET MAUI, доступных в .NET Docs или в виде бесплатного скачиваемого PDF-файла, который можно прочитать в автономном режиме.
.NET MAUI включает поддержку навигации по страницам, которая обычно приводит к взаимодействию пользователя с пользовательским интерфейсом или из самого приложения в результате внутренних изменений состояния на основе логики. Однако навигация может быть сложной для реализации в приложениях, использующих шаблон Model-View-ViewModel (MVVM), так как необходимо выполнить следующие задачи:
- Определение представления для перехода к использованию подхода, который не представляет жесткой связи и зависимостей между представлениями.
- Согласование процесса, с помощью которого нужно перейти к представлению, создается экземпляр и инициализировано. При использовании MVVM представление и модель представления необходимо создать экземпляр и связать друг с другом с помощью контекста привязки представления. Если приложение использует контейнер внедрения зависимостей, экземпляр представлений и моделей представлений может потребовать определенного механизма построения.
- Независимо от того, следует ли выполнять навигацию в режиме представления или в модели представления. При переходе по представлению на страницу для перехода к имени типа представления. Во время навигации создается экземпляр указанного представления вместе с соответствующей моделью представления и другими зависимыми службами. Альтернативный подход — использовать навигацию view-model-first, где страница для перехода ссылается на имя типа модели представления.
- Определение четкого разделения поведения навигации приложения по представлениям и моделям представлений. Шаблон MVVM отделяет пользовательский интерфейс приложения и его презентацию и бизнес-логику, но не предоставляет прямой механизм их объединения. Однако поведение навигации приложения часто охватывает элементы пользовательского интерфейса и презентации приложения. Пользователь часто инициирует навигацию из представления, и представление будет заменено в результате навигации. Однако также может потребоваться инициировать или координировать навигацию из модели представления.
- Определение способа передачи параметров во время навигации для целей инициализации. Например, если пользователь переходит к представлению для обновления сведений о заказе, данные заказа должны передаваться в представление, чтобы он смог отобразить правильные данные.
- Координация навигации для обеспечения соблюдения конкретных бизнес-правил. Например, пользователям может быть предложено перейти от представления, чтобы они могли исправить любые недопустимые данные или отправить или отменить любые изменения данных, внесенные в представлении.
В этой главе рассматриваются эти проблемы путем представления класса службы навигации с именем MauiNavigationService
, который используется для навигации по первой странице представления модели.
Примечание.
Используемый MauiNavigationService
приложением простой и не охватывает все возможные типы навигации. Для типов навигации, необходимых приложению, может потребоваться дополнительная функциональность.
Навигация между страницами
Логика навигации может находиться в коде представления или модели представления, привязанной к данным. Хотя логика навигации в представлении может быть самым простым подходом, это не легко тестировать с помощью модульных тестов. Размещение логики навигации в классах модели представления означает, что логику можно проверить с помощью модульных тестов. Кроме того, модель представления может реализовать логику для управления навигацией, чтобы обеспечить применение определенных бизнес-правил. Например, приложение может не позволить пользователю перейти с страницы, не убедившись, что введенные данные действительны.
Служба навигации обычно вызывается из моделей представления, чтобы повысить удобство тестирования. Однако при переходе к представлениям из моделей представлений требуется, чтобы модели представления ссылались на представления, и особенно представления, с которыми не связана активная модель представления, с которой не рекомендуется. Таким образом, представленный MauiNavigationService
здесь указывает тип модели представления в качестве целевого объекта для перехода.
Приложение eShop с несколькими платформами использует MauiNavigationService
класс для предоставления навигации view-model-first. Этот класс реализует INavigationService
интерфейс, который показан в следующем примере кода:
public interface INavigationService
{
Task InitializeAsync();
Task NavigateToAsync(string route, IDictionary<string, object> routeParameters = null);
Task PopAsync();
}
Этот интерфейс указывает, что класс реализации должен предоставлять следующие методы:
Способ | Характер использования |
---|---|
InitializeAsync |
Выполняет навигацию на одну из двух страниц при запуске приложения. |
NavigateToAsync(string route, IDictionary<string, object> routeParameters = null) |
Выполняет иерархическую навигацию на указанную страницу с помощью зарегистрированного маршрута навигации. Может при необходимости передавать именованные параметры маршрута для обработки на целевой странице |
PopAsync |
Удаляет текущую страницу из стека навигации. |
Примечание.
Интерфейс INavigationService
обычно также указывает GoBackAsync
метод, который используется для программного возврата на предыдущую страницу в стеке навигации. Однако этот метод отсутствует из мультиплатформенного приложения eShop, так как он не требуется.
Создание экземпляра MauiNavigationService
Класс MauiNavigationService
, реализующий INavigationService
интерфейс, регистрируется как однотонный с контейнером внедрения зависимостей в MauiProgram.CreateMauiApp()
методе, как показано в следующем примере кода:
mauiAppBuilder.Services.AddSingleton<INavigationService, MauiNavigationService>();
Затем INavigationService
интерфейс можно разрешить, добавив его в конструктор представлений и моделей представлений, как показано в следующем примере кода:
public AppShell(INavigationService navigationService)
Возвращает ссылку на MauiNavigationService
объект, хранящийся в контейнере внедрения зависимостей.
Класс ViewModelBase
сохраняет MauiNavigationService
экземпляр в свойстве NavigationService
типа INavigationService
. Поэтому все классы модели представления, производные от ViewModelBase
класса, могут использовать NavigationService
свойство для доступа к методам, указанным интерфейсом INavigationService
.
Обработка запросов навигации
.NET MAUI предоставляет несколько способов навигации в приложении. Традиционный способ навигации — это NavigationPage
класс, реализующий иерархическую навигацию, в которой пользователь может перемещаться по страницам, вперед и назад, как нужно. Приложение eShop использует Shell
компонент в качестве корневого контейнера для приложения и в качестве узла навигации. Дополнительные сведения о навигации оболочки см. в разделе "Навигация оболочки" в Центре разработчиков Майкрософт.
Навигация выполняется внутри классов модели представления, вызывая один из NavigateToAsync
методов, указывая путь маршрута для перехода на страницу, как показано в следующем примере кода:
await NavigationService.NavigateToAsync("//Main");
В следующем примере кода показан метод, предоставляемый NavigateToAsync
классом MauiNavigationService
:
public Task NavigateToAsync(string route, IDictionary<string, object> routeParameters = null)
{
return
routeParameters != null
? Shell.Current.GoToAsync(route, routeParameters)
: Shell.Current.GoToAsync(route);
}
Элемент управления .NET MAUIShell
уже знаком с навигацией на основе маршрутов, поэтому NavigateToAsync
метод работает для маскирования этих функций. Метод NavigateToAsync
позволяет указывать данные навигации в качестве аргумента, передаваемого в модель представления, к которой он обычно используется для инициализации. Дополнительные сведения см. в разделе "Передача параметров во время навигации".
Внимание
В .NET MAUIсуществует несколько способов выполнения навигации. В MauiNavigationService
частности, сборка для работы с Shell
. Если вы используете NavigationPage
или TabbedPage
другой механизм навигации, эта служба маршрутизации должна быть обновлена для работы с этими компонентами.
Чтобы зарегистрировать маршруты, необходимые для предоставления сведений о MauiNavigationService
маршрутах из XAML или в коде программной части. В следующем примере показана регистрация маршрутов с помощью XAML.
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:eShop.Views"
x:Class="eShop.AppShell">
<!-- Omitted for brevity -->
<FlyoutItem >
<ShellContent x:Name="login" ContentTemplate="{DataTemplate views:LoginView}" Route="Login" />
</FlyoutItem>
<TabBar x:Name="main" Route="Main">
<ShellContent Title="CATALOG" Route="Catalog" Icon="{StaticResource CatalogIconImageSource}" ContentTemplate="{DataTemplate views:CatalogView}" />
<ShellContent Title="PROFILE" Route="Profile" Icon="{StaticResource ProfileIconImageSource}" ContentTemplate="{DataTemplate views:ProfileView}" />
</TabBar>
</Shell>
В этом примере объекты пользовательского ShellContent
TabBar
интерфейса задают их Route
свойство. Это предпочтительный метод регистрации маршрутов для объектов пользовательского интерфейса, контролируемых a Shell
.
Если у нас есть объекты, которые будут добавлены в стек навигации позже, нам потребуется добавить их с помощью кода. В следующем примере показана регистрация маршрутов в коде программной части.
Routing.RegisterRoute("Filter", typeof(FiltersView));
Routing.RegisterRoute("Basket", typeof(BasketView));
В коде позади мы вызовем Routing.RegisterRoute
метод, который принимает имя маршрута в качестве первого параметра и тип представления в качестве второго параметра. Когда модель представления использует NavigationService
свойство для перехода, объект приложения Shell
будет искать зарегистрированные маршруты и отправлять их в стек навигации.
После создания представления и перехода ApplyQueryAttributes
InitializeAsync
к ней выполняются методы связанной модели представления. Дополнительные сведения см. в разделе "Передача параметров во время навигации".
Навигация при запуске приложения
При запуске Shell
приложения объект устанавливается в качестве корневого представления приложения. После установки Shell
он будет использоваться для управления регистрацией маршрутов и будет присутствовать в корне нашего приложения. Shell
После создания мы можем дождаться, пока оно будет присоединено к приложению, используя OnParentSet
метод для инициализации маршрута навигации. Этот метод показан в следующем примере кода:
protected override async void OnParentSet()
{
base.OnParentSet();
if (Parent is not null)
{
await _navigationService.InitializeAsync();
}
}
Метод использует экземпляр INavigationService
, из которого предоставляется конструктор из внедрения зависимостей и вызывает его InitializeAsync
метод.
В следующем примере кода показана реализация MauiNavigationService.InitializeAsync
метода:
public Task InitializeAsync()
{
return NavigateToAsync(string.IsNullOrEmpty(_settingsService.AuthAccessToken)
? "//Login"
: "//Main/Catalog");
}
Маршрут //Main/Catalog
перемещается, если у приложения есть кэшированный маркер доступа, который используется для проверки подлинности. //Login
В противном случае маршрут переходит к.
Передача параметров во время навигации
Метод NavigateToAsync
, указанный INavigationService
интерфейсом, позволяет указывать данные навигации в виде IDictionary<string, object>
данных, передаваемых в модель представления, к которой он обычно используется для инициализации.
Например, класс содержит объектOrderDetailCommand
, ProfileViewModel
который выполняется при выборе заказа на ProfileView
странице. В свою очередь это выполняет OrderDetailAsync
метод, который показан в следующем примере кода:
private async Task OrderDetailAsync(Order order)
{
if (order is null)
{
return;
}
await NavigationService.NavigateToAsync(
"OrderDetail",
new Dictionary<string, object>{ { "OrderNumber", order.OrderNumber } });
}
Этот метод вызывает навигацию по маршруту, передавая сведения о номере OrderDetail
заказа, выбранному пользователем. Когда платформа внедрения зависимостей создает OrderDetailView
маршрут OrderDetail
вместе с классом OrderDetailViewModel
, назначенным представлению BindingContext
. У OrderDetailViewModel
него есть атрибут, который позволяет получать данные из службы навигации, как показано в приведенном ниже примере кода.
[QueryProperty(nameof(OrderNumber), "OrderNumber")]
public class OrderDetailViewModel : ViewModelBase
{
public int OrderNumber { get; set; }
}
Атрибут QueryProperty
позволяет предоставить параметр для свойства для сопоставления значений и ключа для поиска значений из словаря параметров запроса. В этом примере ключ "OrderNumber" и значение номера заказа было предоставлено во время NavigateToAsync
вызова. Модель представления обнаружила ключ OrderNumber и сопоставила значение со свойством OrderNumber
. Затем OrderNumber
свойство можно использовать позже для получения сведений о полном порядке из экземпляра OrderService
.
Вызов навигации с помощью поведения
Навигация обычно активируется из представления взаимодействием пользователя. Например, LoginView
выполняет навигацию после успешной проверки подлинности. В следующем примере кода показано, как навигация вызывается поведением:
<WebView>
<WebView.Behaviors>
<behaviors:EventToCommandBehavior
EventName="Navigating"
EventArgsConverter="{StaticResource WebNavigatingEventArgsConverter}"
Command="{Binding NavigateCommand}" />
</WebView.Behaviors>
</WebView>
Во время выполнения EventToCommandBehavior
ответит на взаимодействие с WebView
ним. WebView
При переходе на веб-страницу Navigating
событие запустится, которое будет выполняться NavigateCommand
в LoginViewMode
l. По умолчанию аргументы событий для события передаются команде. Эти данные преобразуются при передаче между источником и целевым преобразователем, указанным в EventArgsConverter
свойстве, который возвращает Url
из WebNavigatingEventArgs
него. Поэтому при NavigationCommand
выполнении Url
веб-страницы передается в качестве параметра в зарегистрированное действие.
В свою очередь, метод NavigationCommand
выполняется NavigateAsync
, который показан в следующем примере кода:
private async Task NavigateAsync(string url)
{
// Omitted for brevity.
if (!string.IsNullOrWhiteSpace(accessToken))
{
_settingsService.AuthAccessToken = accessToken;
_settingsService.AuthIdToken = authResponse.IdentityToken;
await NavigationService.NavigateToAsync("//Main/Catalog");
}
}
Этот метод вызывает NavigationService
маршрутизацию //Main/Catalog
приложения в маршрут.
Подтверждение или отмена навигации
Приложению может потребоваться взаимодействовать с пользователем во время операции навигации, чтобы пользователь мог подтвердить или отменить навигацию. Это может потребоваться, например, когда пользователь пытается перейти, прежде чем полностью завершить страницу записи данных. В этом случае приложение должно предоставить уведомление, позволяющее пользователю перейти с страницы или отменить операцию навигации до ее возникновения. Это можно сделать в классе модели представления с помощью ответа от уведомления, чтобы контролировать, вызывается ли навигация.
Итоги
.NET MAUI включает поддержку навигации по страницам, которая обычно приводит к взаимодействию пользователя с пользовательским интерфейсом или из самого приложения в результате внутренних изменений состояния на основе логики. Однако навигация может быть сложной для реализации в приложениях, использующих шаблон MVVM.
В этой главе представлен класс NavigationService, который используется для выполнения навигации по модели представления из моделей представления. Размещение логики навигации в классах модели представления означает, что логика может выполняться с помощью автоматизированных тестов. Кроме того, модель представления может реализовать логику для управления навигацией, чтобы обеспечить применение определенных бизнес-правил.