Поделиться через


Область

Совет

Это содержимое является фрагментом из электронной книги, шаблонов корпоративных приложений с помощью .NET MAUI, доступных в .NET Docs или в виде бесплатного скачиваемого PDF-файла, который можно прочитать в автономном режиме.

Корпоративные шаблоны приложений с помощью эскиза обложки электронной книги .NET MAUI .

.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 в LoginViewModel. По умолчанию аргументы событий для события передаются команде. Эти данные преобразуются при передаче между источником и целевым преобразователем, указанным в 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, который используется для выполнения навигации по модели представления из моделей представления. Размещение логики навигации в классах модели представления означает, что логика может выполняться с помощью автоматизированных тестов. Кроме того, модель представления может реализовать логику для управления навигацией, чтобы обеспечить применение определенных бизнес-правил.