Навигация по корпоративному приложениюEnterprise App Navigation

Xamarin. Forms включает поддержку навигации по страницам, что обычно приводит к взаимодействию пользователя с пользовательским ИНТЕРФЕЙСом или из самого приложения в результате внутренних изменений состояния, управляемых логическими операциями.Xamarin.Forms includes support for page navigation, which typically results from the user's interaction with the UI or from the app itself as a result of internal logic-driven state changes. Однако Навигация может быть сложной для реализации в приложениях, использующих шаблон Model-View-ViewModel (MVVM), так как должны выполняться следующие задачи:However, navigation can be complex to implement in apps that use the Model-View-ViewModel (MVVM) pattern, as the following challenges must be met:

  • Определение представления, к которому осуществляется переход, с использованием подхода, который не обеспечивает тесное связывание и зависимости между представлениями.How to identify the view to be navigated to, using an approach that does not introduce tight coupling and dependencies between views.
  • Способ координации процесса, с которым будет осуществляться переход к представлению, — это экземпляр и инициализирован.How to coordinate the process by which the view to be navigated to is instantiated and initialized. При использовании MVVM модель представления и представления необходимо создать и связать друг с другом через контекст привязки представления.When using MVVM, the view and view model need to be instantiated and associated with each other via the view's binding context. Если приложение использует контейнер внедрения зависимостей, то для создания экземпляров представлений и моделей представлений может потребоваться специальный механизм построения.When an app is using a dependency injection container, the instantiation of views and view models might require a specific construction mechanism.
  • Следует ли выполнять навигацию или Просмотр первой модели.Whether to perform view-first navigation, or view model-first navigation. С помощью навигации «Просмотр — первый» страница, к которой выполняется переход, ссылается на имя типа представления.With view-first navigation, the page to navigate to refers to the name of the view type. Во время навигации создается экземпляр указанного представления вместе с соответствующей моделью представления и другими зависимыми службами.During navigation, the specified view is instantiated, along with its corresponding view model and other dependent services. Альтернативный подход заключается в использовании навигации «Просмотр модели — первый», где страница, к которой осуществляется переход, ссылается на имя типа модели представления.An alternative approach is to use view model-first navigation, where the page to navigate to refers to the name of the view model type.
  • Как четко разделить поведение навигации приложения по представлениям и моделям представления.How to cleanly separate the navigational behavior of the app across the views and view models. Шаблон MVVM обеспечивает разделение между пользовательским интерфейсом приложения и его представлением и бизнес-логикой.The MVVM pattern provides a separation between the app's UI and its presentation and business logic. Однако поведение навигации приложения часто будет охватывать части пользовательского интерфейса и презентации приложения.However, the navigation behavior of an app will often span the UI and presentations parts of the app. Пользователь часто инициирует навигацию из представления, и представление будет заменено в результате навигации.The user will often initiate navigation from a view, and the view will be replaced as a result of the navigation. Однако при этом часто бывает необходимо инициировать или координировать навигацию в модели представления.However, navigation might often also need to be initiated or coordinated from within the view model.
  • Передача параметров во время навигации для целей инициализации.How to pass parameters during navigation for initialization purposes. Например, если пользователь переходит к представлению для обновления сведений о заказе, данные заказа должны быть переданы в представление, чтобы они могли отображать правильные данные.For example, if the user navigates to a view to update order details, the order data will have to be passed to the view so that it can display the correct data.
  • Принцип совместной навигации для обеспечения соблюдения определенных бизнес-правил.How to co-ordinate navigation, to ensure that certain business rules are obeyed. Например, пользователи могут получить запрос перед переходом от представления, чтобы они могли исправлять любые недопустимые данные, или выдать запрос на отправку или отмену изменений данных, внесенных в представление.For example, users might be prompted before navigating away from a view so that they can correct any invalid data or be prompted to submit or discard any data changes that were made within the view.

Эта глава решает эти проблемы, предоставляя NavigationService класс, который используется для выполнения просмотра модели. Первая страница навигации.This chapter addresses these challenges by presenting a NavigationService class that's used to perform view model-first page navigation.

Примечание

Объект NavigationService , используемый приложением, предназначен только для выполнения иерархической навигации между экземплярами ContentPage.The NavigationService used by the app is designed only to perform hierarchical navigation between ContentPage instances. Использование службы для перехода между другими типами страниц может привести к непредвиденному поведению.Using the service to navigate between other page types might result in unexpected behavior.

Логика навигации может находиться в коде программной части представления или в модели представления с привязкой к данным.Navigation logic can reside in a view's code-behind, or in a data bound view model. Хотя логика навигации в представлении может быть самым простым подходом, ее легко тестировать с помощью модульных тестов.While placing navigation logic in a view might be the simplest approach, it is not easily testable through unit tests. Размещение логики навигации в классах модели представления означает, что логику можно использовать в модульных тестах.Placing navigation logic in view model classes means that the logic can be exercised through unit tests. Кроме того, модель представления может реализовать логику для управления навигацией, чтобы обеспечить применение определенных бизнес-правил.In addition, the view model can then implement logic to control navigation to ensure that certain business rules are enforced. Например, приложение может не позволить пользователю перейти с страницы на другую страницу, не убедившись в том, что входные данные являются допустимыми.For example, an app might not allow the user to navigate away from a page without first ensuring that the entered data is valid.

NavigationService Класс обычно вызывается из моделей представления для повышения пригодности для тестирования.A NavigationService class is typically invoked from view models, to promote testability. Однако переход к представлениям из моделей представлений потребует, чтобы модели представления ссылались на представления, а в частности представления, которые не связаны с моделью активного представления, что не рекомендуется.However, navigating to views from view models would require the view models to reference views, and particularly views that the active view model isn't associated with, which is not recommended. Таким образом, NavigationService представленный здесь тип модели представления указывается как целевой объект для перехода.Therefore, the NavigationService presented here specifies the view model type as the target to navigate to.

Мобильное приложение eShopOnContainers использует NavigationService класс для предоставления навигации представления модели.The eShopOnContainers mobile app uses the NavigationService class to provide view model-first navigation. Этот класс реализует INavigationService интерфейс, который показан в следующем примере кода:This class implements the INavigationService interface, which is shown in the following code example:

public interface INavigationService  
{  
    ViewModelBase PreviousPageViewModel { get; }  
    Task InitializeAsync();  
    Task NavigateToAsync<TViewModel>() where TViewModel : ViewModelBase;  
    Task NavigateToAsync<TViewModel>(object parameter) where TViewModel : ViewModelBase;  
    Task RemoveLastFromBackStackAsync();  
    Task RemoveBackStackAsync();  
}

Этот интерфейс указывает, что реализующий класс должен предоставлять следующие методы:This interface specifies that an implementing class must provide the following methods:

МетодMethod ЦельPurpose
InitializeAsync Выполняет переход на одну из двух страниц при запуске приложения.Performs navigation to one of two pages when the app is launched.
NavigateToAsync Выполняет иерархическую навигацию на указанной странице.Performs hierarchical navigation to a specified page.
NavigateToAsync(parameter) Выполняет иерархическую навигацию на указанной странице, передавая параметр.Performs hierarchical navigation to a specified page, passing a parameter.
RemoveLastFromBackStackAsync Удаляет предыдущую страницу из стека навигации.Removes the previous page from the navigation stack.
RemoveBackStackAsync Удаляет все предыдущие страницы из стека навигации.Removes all the previous pages from the navigation stack.

Кроме того INavigationService , интерфейс указывает, что реализующий класс должен PreviousPageViewModel предоставлять свойство.In addition, the INavigationService interface specifies that an implementing class must provide a PreviousPageViewModel property. Это свойство возвращает тип модели представления, связанный с предыдущей страницей в стеке навигации.This property returns the view model type associated with the previous page in the navigation stack.

Примечание

Интерфейс, как правило, также GoBackAsync указывает метод, который используется для программного возврата на предыдущую страницу стека навигации. INavigationServiceAn INavigationService interface would usually also specify a GoBackAsync method, which is used to programmatically return to the previous page in the navigation stack. Однако этот метод отсутствует в мобильном приложении eShopOnContainers, так как он не является обязательным.However, this method is missing from the eShopOnContainers mobile app because it's not required.

Создание экземпляра NavigationServiceCreating the NavigationService Instance

Класс, который INavigationService реализует интерфейс, регистрируется как одноэлементный с помощью контейнера внедрения зависимостей Autofac, как показано в следующем примере кода: NavigationServiceThe NavigationService class, which implements the INavigationService interface, is registered as a singleton with the Autofac dependency injection container, as demonstrated in the following code example:

builder.RegisterType<NavigationService>().As<INavigationService>().SingleInstance();

Интерфейс разрешается в конструкторе ViewModelBase класса, как показано в следующем примере кода: INavigationServiceThe INavigationService interface is resolved in the ViewModelBase class constructor, as demonstrated in the following code example:

NavigationService = ViewModelLocator.Resolve<INavigationService>();

Он возвращает ссылку на NavigationService объект, хранящийся в контейнере внедрения зависимостей Autofac, который создается InitNavigation методом в App классе.This returns a reference to the NavigationService object that's stored in the Autofac dependency injection container, which is created by the InitNavigation method in the App class. Дополнительные сведения см. в разделе переходы при запуске приложения.For more information, see Navigating When the App is Launched.

Класс сохраняет экземпляр в NavigationService свойстве типа INavigationService. NavigationService ViewModelBaseThe ViewModelBase class stores the NavigationService instance in a NavigationService property, of type INavigationService. Таким образом, все классы модели представления, производные от ViewModelBase класса, могут NavigationService использовать свойство для доступа к методам, заданным в INavigationService интерфейсе.Therefore, all view model classes, which derive from the ViewModelBase class, can use the NavigationService property to access the methods specified by the INavigationService interface. Это позволяет избежать издержек при внедрении NavigationService объекта из контейнера внедрения зависимостей Autofac в каждый класс модели представления.This avoids the overhead of injecting the NavigationService object from the Autofac dependency injection container into each view model class.

Обработка запросов навигацииHandling Navigation Requests

Xamarin. Forms предоставляет NavigationPage класс, реализующий иерархическую навигацию, в которой пользователь может перемещаться по страницам, перемещая и обратнее по мере необходимости.Xamarin.Forms provides the NavigationPage class, which implements a hierarchical navigation experience in which the user is able to navigate through pages, forwards and backwards, as desired. Дополнительные сведения об иерархической навигации см. в статье Иерархическая навигация.For more information about hierarchical navigation, see Hierarchical Navigation.

Вместо непосредственного использования NavigationPage класса приложение eShopOnContainers заключает NavigationPage класс в CustomNavigationView класс, как показано в следующем примере кода:Rather than use the NavigationPage class directly, the eShopOnContainers app wraps the NavigationPage class in the CustomNavigationView class, as shown in the following code example:

public partial class CustomNavigationView : NavigationPage  
{  
    public CustomNavigationView() : base()  
    {  
        InitializeComponent();  
    }  

    public CustomNavigationView(Page root) : base(root)  
    {  
        InitializeComponent();  
    }  
}

Цель этого переноса заключается в простоте стилизации NavigationPage экземпляра внутри XAML-файла для класса.The purpose of this wrapping is for ease of styling the NavigationPage instance inside the XAML file for the class.

Навигация выполняется внутри классов модели представления путем вызова одного из NavigateToAsync методов, указывающих тип модели представления для страницы, к которой осуществляется переход, как показано в следующем примере кода:Navigation is performed inside view model classes by invoking one of the NavigateToAsync methods, specifying the view model type for the page being navigated to, as demonstrated in the following code example:

await NavigationService.NavigateToAsync<MainViewModel>();

В следующем примере кода показаны NavigateToAsync методы, предоставляемые NavigationService классом:The following code example shows the NavigateToAsync methods provided by the NavigationService class:

public Task NavigateToAsync<TViewModel>() where TViewModel : ViewModelBase  
{  
    return InternalNavigateToAsync(typeof(TViewModel), null);  
}  

public Task NavigateToAsync<TViewModel>(object parameter) where TViewModel : ViewModelBase  
{  
    return InternalNavigateToAsync(typeof(TViewModel), parameter);  
}

Каждый метод позволяет любому классу модели представления, производному от ViewModelBase класса, выполнять иерархическую навигацию, вызывая InternalNavigateToAsync метод.Each method allows any view model class that derives from the ViewModelBase class to perform hierarchical navigation by invoking the InternalNavigateToAsync method. Кроме того, второй NavigateToAsync метод позволяет указать данные навигации в качестве аргумента, который передается в модель представления, к которой осуществляется переход, где обычно используется для выполнения инициализации.In addition, the second NavigateToAsync method enables navigation data to be specified as an argument that's passed to the view model being navigated to, where it's typically used to perform initialization. Дополнительные сведения см. в разделе Передача параметров во время навигации.For more information, see Passing Parameters During Navigation.

InternalNavigateToAsync Метод выполняет запрос навигации и показан в следующем примере кода:The InternalNavigateToAsync method executes the navigation request, and is shown in the following code example:

private async Task InternalNavigateToAsync(Type viewModelType, object parameter)  
{  
    Page page = CreatePage(viewModelType, parameter);  

    if (page is LoginView)  
    {  
        Application.Current.MainPage = new CustomNavigationView(page);  
    }  
    else  
    {  
        var navigationPage = Application.Current.MainPage as CustomNavigationView;  
        if (navigationPage != null)  
        {  
            await navigationPage.PushAsync(page);  
        }  
        else  
        {  
            Application.Current.MainPage = new CustomNavigationView(page);  
        }  
    }  

    await (page.BindingContext as ViewModelBase).InitializeAsync(parameter);  
}  

private Type GetPageTypeForViewModel(Type viewModelType)  
{  
    var viewName = viewModelType.FullName.Replace("Model", string.Empty);  
    var viewModelAssemblyName = viewModelType.GetTypeInfo().Assembly.FullName;  
    var viewAssemblyName = string.Format(  
                CultureInfo.InvariantCulture, "{0}, {1}", viewName, viewModelAssemblyName);  
    var viewType = Type.GetType(viewAssemblyName);  
    return viewType;  
}  

private Page CreatePage(Type viewModelType, object parameter)  
{  
    Type pageType = GetPageTypeForViewModel(viewModelType);  
    if (pageType == null)  
    {  
        throw new Exception($"Cannot locate page type for {viewModelType}");  
    }  

    Page page = Activator.CreateInstance(pageType) as Page;  
    return page;  
}

Метод выполняет переход к модели представления при первом CreatePage вызове метода. InternalNavigateToAsyncThe InternalNavigateToAsync method performs navigation to a view model by first calling the CreatePage method. Этот метод находит представление, соответствующее указанному типу модели представления, и создает и возвращает экземпляр этого типа представления.This method locates the view that corresponds to the specified view model type, and creates and returns an instance of this view type. Поиск представления, соответствующего типу модели представления, использует подход на основе соглашения, который предполагает, что:Locating the view that corresponds to the view model type uses a convention-based approach, which assumes that:

  • Представления находятся в той же сборке, что и типы моделей представления.Views are in the same assembly as view model types.
  • Представления находятся в. Дочернее пространство имен views.Views are in a .Views child namespace.
  • Модели представления находятся в. Дочернее пространство имен ViewModel.View models are in a .ViewModels child namespace.
  • Имена представлений соответствуют именам моделей представления с удаленным "моделью".View names correspond to view model names, with "Model" removed.

При создании экземпляра представления он связывается с соответствующей моделью представления.When a view is instantiated, it's associated with its corresponding view model. Дополнительные сведения о том, как это происходит, см. в разделе Автоматическое создание модели представления с локатором модели представления.For more information about how this occurs, see Automatically Creating a View Model with a View Model Locator.

Если создаваемое представление имеет значение LoginView, оно упаковывается внутри нового экземпляра CustomNavigationView Application.Current.MainPage класса и назначается свойству.If the view being created is a LoginView, it's wrapped inside a new instance of the CustomNavigationView class and assigned to the Application.Current.MainPage property. В противном случае извлекается PushAsync экземпляриприусловии,чтооннеравенnull,вызываетсяметоддляпринудительнойотправкипредставления,создаваемоговстекенавигации.CustomNavigationViewOtherwise, the CustomNavigationView instance is retrieved, and provided that it isn't null, the PushAsync method is invoked to push the view being created onto the navigation stack. Однако если полученный CustomNavigationView экземпляр имеет значение null, создаваемое представление упаковывается внутри нового экземпляра CustomNavigationView класса и назначается Application.Current.MainPage свойству.However, If the retrieved CustomNavigationView instance is null, the view being created is wrapped inside a new instance of the CustomNavigationView class and assigned to the Application.Current.MainPage property. Этот механизм гарантирует, что при переходе страницы будут правильно добавляться в стек навигации, когда он пуст и когда он содержит данные.This mechanism ensures that during navigation, pages are added correctly to the navigation stack both when it's empty, and when it contains data.

Совет

Рассмотрите возможность кэширования страниц.Consider caching pages. Кэширование страниц приводит к потреблению памяти для представлений, которые в настоящее время не отображаются.Page caching results in memory consumption for views that are not currently displayed. Однако без кэширования страницы это означает, что синтаксический анализ XAML и создание страницы и ее модели представления будут выполняться каждый раз при переходе к новой странице, что может оказать влияние на производительность сложной страницы.However, without page caching it does mean that XAML parsing and construction of the page and its view model will occur every time a new page is navigated to, which can have a performance impact for a complex page. Для хорошо спроектированной страницы, которая не использует слишком много элементов управления, производительность должна быть достаточной.For a well-designed page that does not use an excessive number of controls, the performance should be sufficient. Однако кэширование страниц может помочь в случае возникновения длительной загрузки страниц.However, page caching might help if slow page loading times are encountered.

После создания представления и перехода к InitializeAsync нему выполняется метод связанной модели представления представления.After the view is created and navigated to, the InitializeAsync method of the view's associated view model is executed. Дополнительные сведения см. в разделе Передача параметров во время навигации.For more information, see Passing Parameters During Navigation.

При запуске InitNavigation приложения вызывается метод App в классе.When the app is launched, the InitNavigation method in the App class is invoked. Этот метод показан в следующем примере кода:The following code example shows this method:

private Task InitNavigation()  
{  
    var navigationService = ViewModelLocator.Resolve<INavigationService>();  
    return navigationService.InitializeAsync();  
}

Метод создает новый NavigationService объект в контейнере внедрения зависимостей Autofac и возвращает ссылку на него перед вызовом InitializeAsync метода.The method creates a new NavigationService object in the Autofac dependency injection container, and returns a reference to it, before invoking its InitializeAsync method.

Примечание

Когда интерфейс разрешается ViewModelBase классом, контейнер NavigationService возвращает ссылку на объект, который был создан при вызове метода инитнавигатион. INavigationServiceWhen the INavigationService interface is resolved by the ViewModelBase class, the container returns a reference to the NavigationService object that was created when the InitNavigation method is invoked.

В следующем примере кода показан NavigationService InitializeAsync метод:The following code example shows the NavigationService InitializeAsync method:

public Task InitializeAsync()  
{  
    if (string.IsNullOrEmpty(Settings.AuthAccessToken))  
        return NavigateToAsync<LoginViewModel>();  
    else  
        return NavigateToAsync<MainViewModel>();  
}

MainView Переходит к, если приложение имеет кэшированный маркер доступа, который используется для проверки подлинности.The MainView is navigated to if the app has a cached access token, which is used for authentication. LoginView В противном случае переходит к.Otherwise, the LoginView is navigated to.

Дополнительные сведения о контейнере внедрения зависимостей Autofac см. в разделе Введение в внедрение зависимостей.For more information about the Autofac dependency injection container, see Introduction to Dependency Injection.

Передача параметров во время навигацииPassing Parameters During Navigation

Один из NavigateToAsync методов, INavigationService заданных интерфейсом, позволяет указать данные навигации в качестве аргумента, который передается в модель представления, к которой осуществляется переход, где обычно используется для выполнения инициализации.One of the NavigateToAsync methods, specified by the INavigationService interface, enables navigation data to be specified as an argument that's passed to the view model being navigated to, where it's typically used to perform initialization.

Например, ProfileViewModel класс содержит объект OrderDetailCommand , который выполняется, когда пользователь ProfileView выбирает заказ на странице.For example, the ProfileViewModel class contains an OrderDetailCommand that's executed when the user selects an order on the ProfileView page. В свою очередь, выполняет OrderDetailAsync метод, который показан в следующем примере кода:In turn, this executes the OrderDetailAsync method, which is shown in the following code example:

private async Task OrderDetailAsync(Order order)  
{  
    await NavigationService.NavigateToAsync<OrderDetailViewModel>(order);  
}

Этот метод вызывает навигацию OrderDetailViewModelв, Order передавая экземпляр, который представляет порядок, выбранный пользователем на ProfileView странице.This method invokes navigation to the OrderDetailViewModel, passing an Order instance that represents the order that the user selected on the ProfileView page. NavigationService Когда класс OrderDetailViewсоздает, OrderDetailViewModel экземплярклассасоздаетсяиназначаетсяBindingContextдля представления.When the NavigationService class creates the OrderDetailView, the OrderDetailViewModel class is instantiated and assigned to the view's BindingContext. После перехода к OrderDetailView InternalNavigateToAsync службам метод выполняет InitializeAsync метод модели представления, связанной с представлением.After navigating to the OrderDetailView, the InternalNavigateToAsync method executes the InitializeAsync method of the view's associated view model.

InitializeAsync Метод определяетсяViewModelBase в классе как метод, который можно переопределить.The InitializeAsync method is defined in the ViewModelBase class as a method that can be overridden. Этот метод задает object аргумент, представляющий данные, передаваемые в модель представления во время операции навигации.This method specifies an object argument that represents the data to be passed to a view model during a navigation operation. Поэтому Просмотрите классы модели, которые хотят получить данные из операции перехода, и предоставьте собственную реализацию InitializeAsync метода для выполнения необходимой инициализации.Therefore, view model classes that want to receive data from a navigation operation provide their own implementation of the InitializeAsync method to perform the required initialization. В следующем примере кода показан InitializeAsync метод OrderDetailViewModel из класса:The following code example shows the InitializeAsync method from the OrderDetailViewModel class:

public override async Task InitializeAsync(object navigationData)  
{  
    if (navigationData is Order)  
    {  
        ...  
        Order = await _ordersService.GetOrderAsync(  
                        Convert.ToInt32(order.OrderNumber), authToken);  
        ...  
    }  
}

Этот метод извлекает Order экземпляр, который был передан в модель представления во время операции навигации, и использует его для получения полных сведений о заказе OrderService из экземпляра.This method retrieves the Order instance that was passed into the view model during the navigation operation, and uses it to retrieve the full order details from the OrderService instance.

Вызов навигации с помощью поведенийInvoking Navigation using Behaviors

Навигация обычно запускается из представления с помощью взаимодействия с пользователем.Navigation is usually triggered from a view by a user interaction. Например, LoginView выполняет навигацию после успешной проверки подлинности.For example, the LoginView performs navigation following successful authentication. В следующем примере кода показано, как вызывается Навигация с помощью поведения:The following code example shows how the navigation is invoked by a behavior:

<WebView ...>  
    <WebView.Behaviors>  
        <behaviors:EventToCommandBehavior  
            EventName="Navigating"  
            EventArgsConverter="{StaticResource WebNavigatingEventArgsConverter}"  
            Command="{Binding NavigateCommand}" />  
    </WebView.Behaviors>  
</WebView>

Во время выполнения EventToCommandBehavior будет реагировать на взаимодействие WebViewс.At runtime, the EventToCommandBehavior will respond to interaction with the WebView. При переходе на веб-страницу Navigating будет срабатывать событие NavigateCommand , которое LoginViewModelбудет выполняться в. WebViewWhen the WebView navigates to a web page, the Navigating event will fire, which will execute the NavigateCommand in the LoginViewModel. По умолчанию аргументы события для события передаются в команду.By default, the event arguments for the event are passed to the command. Эти данные преобразуются при передаче между источником и целевым объектом преобразователем, указанным в EventArgsConverter свойстве, которое Url возвращает из WebNavigatingEventArgs.This data is converted as it's passed between source and target by the converter specified in the EventArgsConverter property, which returns the Url from the WebNavigatingEventArgs. Таким образом, при NavigationCommand выполнении объект URL веб-страницы передается в качестве параметра зарегистрированному. ActionTherefore, when the NavigationCommand is executed, the Url of the web page is passed as a parameter to the registered Action.

В свою очередь NavigationCommand , выполняет NavigateAsync метод, который показан в следующем примере кода:In turn, the NavigationCommand executes the NavigateAsync method, which is shown in the following code example:

private async Task NavigateAsync(string url)  
{  
    ...          
    await NavigationService.NavigateToAsync<MainViewModel>();  
    await NavigationService.RemoveLastFromBackStackAsync();  
    ...  
}

Этот метод вызывает навигацию на MainViewModel, а также при переходе LoginView Удаляет страницу из стека навигации.This method invokes navigation to the MainViewModel, and following navigation, removes the LoginView page from the navigation stack.

Подтверждение или отмена навигацииConfirming or Cancelling Navigation

Приложению может потребоваться взаимодействовать с пользователем во время операции навигации, чтобы пользователь мог подтвердить или отменить навигацию.An app might need to interact with the user during a navigation operation, so that the user can confirm or cancel navigation. Это может быть необходимо, например, когда пользователь пытается выполнить переход до полного заполнения страницы ввода данных.This might be necessary, for example, when the user attempts to navigate before having fully completed a data entry page. В этом случае приложение должно предоставить уведомление, позволяющее пользователю перейти с страницы или отменить операцию перехода до ее возникновения.In this situation, an app should provide a notification that allows the user to navigate away from the page, or to cancel the navigation operation before it occurs. Это можно сделать в классе модели представления с помощью ответа от уведомления, чтобы определить, вызывается ли переход.This can be achieved in a view model class by using the response from a notification to control whether or not navigation is invoked.

СводкаSummary

Xamarin. Forms включает поддержку навигации по страницам, что обычно приводит к взаимодействию пользователя с пользовательским ИНТЕРФЕЙСом или из самого приложения в результате внутренних изменений состояния, управляемых логическими операциями.Xamarin.Forms includes support for page navigation, which typically results from the user's interaction with the UI, or from the app itself, as a result of internal logic-driven state changes. Однако Навигация может быть сложной для реализации в приложениях, использующих шаблон MVVM.However, navigation can be complex to implement in apps that use the MVVM pattern.

В этой главе представлен NavigationService класс, который используется для выполнения навигации по модели представления при первом просмотре моделей.This chapter presented a NavigationService class, which is used to perform view model-first navigation from view models. Размещение логики навигации в классах представления позволяет выполнять логику с помощью автоматических тестов.Placing navigation logic in view model classes means that the logic can be exercised through automated tests. Кроме того, модель представления может реализовать логику для управления навигацией, чтобы обеспечить применение определенных бизнес-правил.In addition, the view model can then implement logic to control navigation to ensure that certain business rules are enforced.