Branch de Referência
Compare navigation com dependency_injection
O .NET MAUI inclui suporte para navegação de página, que normalmente resulta da interação do usuário com a interface do usuário ou do próprio aplicativo como resultado de alterações internas de estado de objetos.
A lógica de navegação pode residir no code-behind de uma View ou em um ViewModel associado a dados. Embora colocar a lógica de navegação em uma View possa ser a abordagem mais direta, ela não é facilmente testável por meio de testes de unidade. Colocar a lógica de navegação em classes de ViewModel significa que a lógica pode ser verificada por meio de testes de unidade. Além disso, o ViewModel pode implementar a lógica para controlar a navegação para garantir que certas regras de negócios sejam aplicadas. Por exemplo, um aplicativo pode não permitir que o usuário saia de uma página sem primeiro garantir que os dados inseridos sejam válidos.
Um serviço de navegação é normalmente invocado a partir de ViewModels, a fim de promover a testabilidade. No entanto, navegar para Views dos ViewModels exigiria que os ViewModels fizessem referência a View e, particularmente, Views às quais o ViewModel ativo não está associado, o que não é recomendado. Portanto, o MauiNavigationService apresentado aqui especifica o tipo de ViewModel como o destino para o qual navegar.
O aplicativo multiplataforma MinhaQualidadeMaui usa a classe MauiNavigationService para fornecer navegação ao ViewModel. Essa classe implementa a interface INavigationService, que é mostrada no seguinte exemplo de código:
public interface INavigationService { Task InitializeAsync(string data); Task NavigateToAsync(string route, IDictionary<string, object> routeParameters = null); Task PopAsync(); }
Essa interface especifica que uma classe de implementação deve fornecer os seguintes métodos:
Método | Propósito |
---|---|
InitializeAsync | Executa a navegação quando o aplicativo é iniciado. |
NavigateToAsync | Executa navegação hierárquica para uma página especifica usando uma rota de navegação registrada. Pode, opcionalmente, passar parâmetros de rota nomeados para usar no processamento da página de destino. |
PopAsync | Remove a página atual da pilha de navegação. |
O .NET MAUI fornece várias maneiras de navegar em um aplicativo. A maneira tradicional de navegar é com a classe NavigationPage
, que implementa uma experiência de navegação hierárquica na qual o usuário pode navegar pelas páginas, para frente e para trás, conforme desejar. No aplicativo MinhaQualidadeMaui foi implementado o componente Shell
como contêiner raiz e um host de navegação.
A navegação é realizada dentro das classes ViewModel invocando um dos métodos NavigateToAsync
, especificando o caminho da rota para a página que está sendo navegada, conforme demonstrado no exemplo de código a seguir:
await _navigationService.NavigateToAsync("QRCodePage");
O exemplo de código a seguir mostra o método NavigateToAsync
fornecido pela classe MauiNavigationService
:
public Task NavigateToAsync(string route, IDictionary<string, object> routeParameters = null) { var shellNavigation = new ShellNavigationState(route); return routeParameters != null ? Shell.Current.GoToAsync(shellNavigation, true, routeParameters) : Shell.Current.GoToAsync(shellNavigation, true); }
O controle Shell
já está familiarizado com a navegação baseada em rota, portanto, o método NavigateToAsync
funciona para mascarar essa funcionalidade. O método NavigateToAsync
permite que os dados de navegação sejam especificados como um argumento que é passado para o ViewModel que está sendo navegado, onde normalmente é usado para executar a inicialização.
O método NavigateToAsync
, especificado pela interface INavigationService
, permite que os dados de navegação sejam especificados como um IDictionary<string, object>
dos dados que são passados para o ViewModel que está sendo navegado, onde normalmente é usado para executar a inicialização.
Por exemplo, a classe LoginViewModel
contém um ConfigurationCommand
que é executado quando o usuário clica no botão de configuração na página RMSLoginPage
. Por sua vez, isso executa o método OnConfigurate_ClickedAsync
, que é mostrado no seguinte exemplo de código:
protected override async void OnConfigurate_ClickedAsync() { bool isExBase = CheckIsExBase(); if (!isExBase) { await _navigationService.NavigateToAsync("ReconfigPage", new Dictionary<string, object> { { "IsBaseExemplo", isExBase } }); } ... }
Este método invoca a navegação para a rota ReconfigPage
, passando a propriedade IsBaseExemplo como parâmetro.
O ReconfigViewModel
possui um atributo adicionado a ele que permite receber dados do serviço de navegação, conforme mostrado no exemplo de código abaixo.
[QueryProperty(nameof(IsBaseExemplo), "IsBaseExemplo")] public class ReconfigViewModel : RMSReconfigViewModel { public bool IsBaseExemplo { set => CanBackup = !value && !string.IsNullOrEmpty(App.GetContexto().User); } ... }
O atributo QueryProperty
nos permite fornecer um parâmetro para uma propriedade para mapear valores e uma chave para localizar valores do dicionário de parâmetros de consulta. Neste exemplo, a chave "IsBaseExemplo" e o valor dela foram fornecidos durante a chamada NavigateToAsync
. O ViewModel encontrou a chave "IsBaseExemplo" e mapeou o valor para a propriedade IsBaseExemplo
.