Delen via


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.

Enterprise Application Patterns Using .NET MAUI eBook cover thumbnail.

.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.

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 Shellte 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.

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 LoginViewModel 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 WebNavigatingEventArgseigenschap 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.