Navigatie
Tip
Deze inhoud is een fragment uit het eBook, Enterprise Application Patterns Using .NET MAUI, beschikbaar op .NET Docs of als een gratis downloadbare PDF die offline kan worden gelezen.
.NET MAUI bevat ondersteuning voor paginanavigatie, wat meestal het gevolg is van de interactie van de gebruiker met de gebruikersinterface of van de app zelf als gevolg van interne logicagestuurde statuswijzigingen. Navigatie kan echter complex zijn om te implementeren in apps die gebruikmaken van het MVVM-patroon (Model-View-ViewModel), omdat aan de volgende uitdagingen moet worden voldaan:
- Het identificeren van de weergave die moet worden genavigeerd met behulp van een benadering die geen nauwe koppeling en afhankelijkheden tussen weergaven introduceert.
- Het coördineren van het proces waarnaar de weergave moet worden genavigeerd en geïnitialiseerd. Wanneer u MVVM gebruikt, moet het weergave- en weergavemodel worden geïnstantieerd en aan elkaar gekoppeld via de bindingscontext van de weergave. Wanneer een app gebruikmaakt van een container voor afhankelijkheidsinjectie, is voor de instantiëring van weergaven en weergavemodellen mogelijk een specifiek constructiemechanisme vereist.
- Hiermee wordt aangegeven of u nu eerst navigatie wilt uitvoeren, of navigatie op basis van modelweergaven. Met weergave-eerste navigatie verwijst de pagina om te navigeren naar de naam van het weergavetype. Tijdens de navigatie wordt de opgegeven weergave geïnstantieerd, samen met het bijbehorende weergavemodel en andere afhankelijke services. Een alternatieve benadering is het gebruik van navigatie voor weergavemodel-first, waarbij de pagina waarnaar moet worden genavigeert, verwijst naar de naam van het type weergavemodel.
- Bepalen hoe u het navigatiegedrag van de app op schone wijze kunt scheiden over de weergaven en weergavemodellen. Het MVVM-patroon scheidt de gebruikersinterface van de app en de bijbehorende presentatie en bedrijfslogica, maar biedt geen direct mechanisme voor het koppelen ervan. Het navigatiegedrag van een app omvat echter vaak de gebruikersinterface en presentatieonderdelen van de app. De gebruiker initieert vaak navigatie vanuit een weergave en de weergave wordt vervangen als gevolg van de navigatie. Navigatie moet echter vaak ook worden gestart of gecoördineerd vanuit het weergavemodel.
- Bepalen hoe parameters worden doorgegeven tijdens de navigatie voor initialisatiedoeleinden. Als de gebruiker bijvoorbeeld naar een weergave navigeert om ordergegevens bij te werken, moeten de ordergegevens worden doorgegeven aan de weergave, zodat de juiste gegevens kunnen worden weergegeven.
- Coördinatie van navigatie om ervoor te zorgen dat specifieke bedrijfsregels worden nageleefd. Gebruikers kunnen bijvoorbeeld worden gevraagd om weg te navigeren vanuit een weergave, zodat ze ongeldige gegevens kunnen corrigeren of worden gevraagd gegevenswijzigingen in te dienen of te verwijderen die in de weergave zijn aangebracht.
In dit hoofdstuk worden deze uitdagingen aangepakt door een navigatieserviceklasse MauiNavigationService
te presenteren die wordt gebruikt voor het uitvoeren van navigatie op het eerste pagina-weergavemodel.
Notitie
Het MauiNavigationService
gebruik door de app is simplistisch en omvat niet alle mogelijke navigatietypen. Voor de typen navigatie die uw toepassing nodig heeft, is mogelijk extra functionaliteit vereist.
Navigeren tussen pagina's
Navigatielogica kan zich bevinden in de code-achter of een gegevensgebonden weergavemodel van een weergave. Hoewel het plaatsen van navigatielogica in een weergave de eenvoudigste benadering is, is het niet eenvoudig te testen via eenheidstests. Het plaatsen van navigatielogica in weergavemodelklassen betekent dat de logica kan worden geverifieerd via eenheidstests. Daarnaast kan het weergavemodel logica implementeren om navigatie te beheren om ervoor te zorgen dat bepaalde bedrijfsregels worden afgedwongen. Een app kan bijvoorbeeld niet toestaan dat de gebruiker weg van een pagina navigeert zonder eerst ervoor te zorgen dat de ingevoerde gegevens geldig zijn.
Een navigatieservice wordt doorgaans aangeroepen vanuit weergavemodellen om de testbaarheid te bevorderen. Als u echter naar weergaven van weergavemodellen navigeert, moeten de weergavemodellen verwijzen naar weergaven en met name weergaven waaraan het actieve weergavemodel niet is gekoppeld, wat niet wordt aanbevolen. Daarom geeft de MauiNavigationService
gepresenteerde hier het type weergavemodel op als het doel om naar te navigeren.
De eShop-app voor meerdere platformen maakt gebruik van de MauiNavigationService
klasse voor het bieden van navigatie op basis van view-model-first. Deze klasse implementeert de INavigationService
interface, die wordt weergegeven in het volgende codevoorbeeld:
public interface INavigationService
{
Task InitializeAsync();
Task NavigateToAsync(string route, IDictionary<string, object> routeParameters = null);
Task PopAsync();
}
Deze interface geeft aan dat een implementatieklasse de volgende methoden moet bieden:
Methode | Doel |
---|---|
InitializeAsync |
Hiermee wordt een navigatie uitgevoerd naar een van de twee pagina's wanneer de app wordt gestart. |
NavigateToAsync(string route, IDictionary<string, object> routeParameters = null) |
Voert hiërarchische navigatie naar een opgegeven pagina uit met behulp van een geregistreerde navigatieroute. Kan eventueel benoemde routeparameters doorgeven die moeten worden gebruikt voor verwerking op de doelpagina |
PopAsync |
Hiermee verwijdert u de huidige pagina uit de navigatiestack. |
Notitie
Een INavigationService
interface zou meestal ook een GoBackAsync
methode opgeven, die wordt gebruikt om programmatisch terug te keren naar de vorige pagina in de navigatiestack. Deze methode ontbreekt echter in de eShop-app met meerdere platforms, omdat deze niet vereist is.
Het exemplaar van MauiNavigationService maken
De MauiNavigationService
klasse, die de INavigationService
interface implementeert, wordt geregistreerd als een singleton met de container voor afhankelijkheidsinjectie in de MauiProgram.CreateMauiApp()
methode, zoals wordt weergegeven in het volgende codevoorbeeld:
mauiAppBuilder.Services.AddSingleton<INavigationService, MauiNavigationService>();
De INavigationService
interface kan vervolgens worden opgelost door deze toe te voegen aan de constructor van onze weergaven en weergavemodellen, zoals wordt weergegeven in het volgende codevoorbeeld:
public AppShell(INavigationService navigationService)
Hiermee wordt een verwijzing geretourneerd naar het MauiNavigationService
object dat is opgeslagen in de container voor afhankelijkheidsinjectie.
De ViewModelBase
klasse slaat het exemplaar op in een NavigationService
eigenschap van het MauiNavigationService
typeINavigationService
. Daarom kunnen alle view-model-klassen, die zijn afgeleid van de ViewModelBase
klasse, de NavigationService
eigenschap gebruiken om toegang te krijgen tot de methoden die zijn opgegeven door de INavigationService
interface.
Navigatieaanvragen verwerken
.NET MAUI biedt meerdere manieren om in een toepassing te navigeren. De traditionele manier om te navigeren is met de NavigationPage
klasse, die een hiërarchische navigatie-ervaring implementeert waarin de gebruiker naar wens door pagina's, vooruit en achteruit kan navigeren. De eShop-app gebruikt het Shell
onderdeel als de hoofdcontainer voor de toepassing en als navigatiehost. Zie Shell-navigatie in het Microsoft Developer Center voor meer informatie over Shell-navigatie.
Navigatie wordt uitgevoerd in weergavemodelklassen door een van de NavigateToAsync
methoden aan te roepen, waarbij u het routepad opgeeft waar de pagina naartoe wordt genavigeerd, zoals wordt weergegeven in het volgende codevoorbeeld:
await NavigationService.NavigateToAsync("//Main");
In het volgende codevoorbeeld ziet u de NavigateToAsync
methode die door de MauiNavigationService
klasse wordt geleverd:
public Task NavigateToAsync(string route, IDictionary<string, object> routeParameters = null)
{
return
routeParameters != null
? Shell.Current.GoToAsync(route, routeParameters)
: Shell.Current.GoToAsync(route);
}
Het .NET-besturingselement MAUIShell
is al bekend met navigatie op basis van route, dus de NavigateToAsync
methode werkt om deze functionaliteit te maskeren. Met de NavigateToAsync
methode kunnen navigatiegegevens worden opgegeven als een argument dat wordt doorgegeven aan het weergavemodel waarnaar wordt genavigeerd, waar deze doorgaans wordt gebruikt om initialisatie uit te voeren. Zie Parameters doorgeven tijdens de navigatie voor meer informatie.
Belangrijk
Er zijn meerdere manieren om navigatie uit te voeren in .NET MAUI. De MauiNavigationService
is specifiek gebouwd om mee Shell
te werken. Als u een NavigationPage
of TabbedPage
ander navigatiemechanisme gebruikt, moet deze routeringsservice worden bijgewerkt om deze onderdelen te kunnen gebruiken.
Als u routes wilt registreren voor de MauiNavigationService
routegegevens van XAML of in de code-behind. In het volgende voorbeeld ziet u de registratie van routes via 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>
In dit voorbeeld stellen de objecten en TabBar
gebruikersinterfaceobjecten ShellContent
hun Route
eigenschap in. Dit is de voorkeursmethode voor het registreren van routes voor gebruikersinterfaceobjecten die worden beheerd door een Shell
.
Als we objecten hebben die op een later tijdstip aan de navigatiestack worden toegevoegd, moeten we deze toevoegen via code-behind. In het volgende voorbeeld ziet u de registratie van routes in code-behind.
Routing.RegisterRoute("Filter", typeof(FiltersView));
Routing.RegisterRoute("Basket", typeof(BasketView));
In code-behind roepen we de Routing.RegisterRoute
methode aan die een routenaam als de eerste parameter gebruikt en een weergavetype als de tweede parameter. Wanneer een weergavemodel de NavigationService
eigenschap gebruikt om te navigeren, zoekt het object van Shell
de toepassing naar geregistreerde routes en pusht deze naar de navigatiestack.
Nadat de weergave is gemaakt en hiernatoe is genavigeerd, worden de ApplyQueryAttributes
en InitializeAsync
methoden van het bijbehorende weergavemodel van de weergave uitgevoerd. Zie Parameters doorgeven tijdens de navigatie voor meer informatie.
Navigeren wanneer de app wordt gestart
Wanneer de app wordt gestart, wordt een Shell
object ingesteld als de hoofdweergave van de toepassing. Zodra deze is ingesteld, wordt deze gebruikt om de Shell
routeregistratie te beheren en wordt deze in de hoofdmap van onze toepassing in de toekomst weergegeven. Zodra de app Shell
is gemaakt, kunnen we wachten tot deze is gekoppeld aan de toepassing met behulp van de OnParentSet
methode om de navigatieroute te initialiseren. In het volgende codevoorbeeld ziet u deze methode:
protected override async void OnParentSet()
{
base.OnParentSet();
if (Parent is not null)
{
await _navigationService.InitializeAsync();
}
}
De methode maakt gebruik van een exemplaar waarvan de constructor wordt geleverd op basis van INavigationService
afhankelijkheidsinjectie en roept de InitializeAsync
bijbehorende methode aan.
In het volgende codevoorbeeld ziet u de implementatie van de MauiNavigationService.InitializeAsync
methode:
public Task InitializeAsync()
{
return NavigateToAsync(string.IsNullOrEmpty(_settingsService.AuthAccessToken)
? "//Login"
: "//Main/Catalog");
}
De //Main/Catalog
route wordt genavigeerd als de app een toegangstoken in de cache heeft, dat wordt gebruikt voor verificatie. Anders wordt de //Login
route naartoe genavigeerd.
Parameters doorgeven tijdens navigatie
Met NavigateToAsync
de methode, die is opgegeven door de INavigationService
interface, kunnen navigatiegegevens worden opgegeven als een IDictionary<string, object>
gegevens die worden doorgegeven aan het weergavemodel waarnaar wordt genavigeerd, waar het meestal wordt gebruikt om initialisatie uit te voeren.
De klasse bevat bijvoorbeeld ProfileViewModel
een OrderDetailCommand
klasse die wordt uitgevoerd wanneer de gebruiker een order op de ProfileView
pagina selecteert. Op zijn beurt wordt de OrderDetailAsync
methode uitgevoerd, die wordt weergegeven in het volgende codevoorbeeld:
private async Task OrderDetailAsync(Order order)
{
if (order is null)
{
return;
}
await NavigationService.NavigateToAsync(
"OrderDetail",
new Dictionary<string, object>{ { "OrderNumber", order.OrderNumber } });
}
Met deze methode wordt navigatie aan de OrderDetail
route aangeroepen, waarbij de ordernummergegevens worden doorgegeven aan de volgorde die de gebruiker heeft geselecteerd. Wanneer het afhankelijkheidsinjectieframework de OrderDetailView
voor de OrderDetail
route maakt, samen met de OrderDetailViewModel
klasse die is toegewezen aan de weergave BindingContext
. Er OrderDetailViewModel
is een kenmerk toegevoegd waarmee het gegevens van de navigatieservice kan ontvangen, zoals wordt weergegeven in het onderstaande codevoorbeeld.
[QueryProperty(nameof(OrderNumber), "OrderNumber")]
public class OrderDetailViewModel : ViewModelBase
{
public int OrderNumber { get; set; }
}
Met QueryProperty
het kenmerk kunnen we een parameter voor een eigenschap opgeven om waarden toe te wijzen aan en een sleutel om waarden te vinden uit de woordenlijst met queryparameters. In dit voorbeeld zijn de sleutel 'OrderNummer' en de waarde van het ordernummer opgegeven tijdens de NavigateToAsync
aanroep. Het weergavemodel heeft de sleutel OrderNumber gevonden en de waarde aan de OrderNumber
eigenschap toegewezen. De OrderNumber
eigenschap kan vervolgens op een later tijdstip worden gebruikt om de volledige ordergegevens van het OrderService
exemplaar op te halen.
Navigatie aanroepen met gedrag
Navigatie wordt meestal geactiveerd vanuit een weergave door een gebruikersinteractie. Het LoginView
voert bijvoorbeeld navigatie uit na geslaagde verificatie. In het volgende codevoorbeeld ziet u hoe de navigatie wordt aangeroepen door een gedrag:
<WebView>
<WebView.Behaviors>
<behaviors:EventToCommandBehavior
EventName="Navigating"
EventArgsConverter="{StaticResource WebNavigatingEventArgsConverter}"
Command="{Binding NavigateCommand}" />
</WebView.Behaviors>
</WebView>
Tijdens runtime reageert de EventToCommandBehavior
reactie op interactie met de WebView
. Wanneer de WebView
pagina naar een webpagina navigeert, wordt de Navigating
gebeurtenis geactiveerd, waarmee de NavigateCommand
in de LoginViewMode
l wordt uitgevoerd. Standaard worden de gebeurtenisargumenten voor de gebeurtenis doorgegeven aan de opdracht. Deze gegevens worden geconverteerd omdat deze worden doorgegeven tussen de bron en het doel door het conversieprogramma dat is opgegeven in de EventArgsConverter
eigenschap, die de van de Url
WebNavigatingEventArgs
eigenschap retourneert. Wanneer de NavigationCommand
webpagina wordt uitgevoerd, wordt de Url
webpagina daarom doorgegeven als een parameter aan de geregistreerde actie.
Op zijn beurt NavigationCommand
wordt de NavigateAsync
methode uitgevoerd, die wordt weergegeven in het volgende codevoorbeeld:
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");
}
}
Met deze methode wordt de toepassing naar de //Main/Catalog
route gerouteerdNavigationService
.
Navigatie bevestigen of annuleren
Een app moet mogelijk communiceren met de gebruiker tijdens een navigatiebewerking, zodat de gebruiker de navigatie kan bevestigen of annuleren. Dit kan bijvoorbeeld nodig zijn wanneer de gebruiker probeert te navigeren voordat de gegevensinvoerpagina volledig is voltooid. In dit geval moet een app een melding opgeven waarmee de gebruiker van de pagina kan navigeren of de navigatiebewerking kan annuleren voordat deze plaatsvindt. Dit kan worden bereikt in een weergavemodelklasse door het antwoord van een melding te gebruiken om te bepalen of navigatie al dan niet wordt aangeroepen.
Samenvatting
.NET MAUI bevat ondersteuning voor paginanavigatie, die doorgaans het gevolg is van de interactie van de gebruiker met de gebruikersinterface of van de app zelf, als gevolg van interne logicagestuurde statuswijzigingen. Navigatie kan echter complex zijn om te implementeren in apps die gebruikmaken van het MVVM-patroon.
In dit hoofdstuk werd een Navigatieservice-klasse gepresenteerd, die wordt gebruikt om view-model-first navigatie uit weergavemodellen uit te voeren. Het plaatsen van navigatielogica in weergavemodelklassen betekent dat de logica kan worden uitgevoerd via geautomatiseerde tests. Daarnaast kan het weergavemodel logica implementeren om navigatie te beheren om ervoor te zorgen dat bepaalde bedrijfsregels worden afgedwongen.