Navigation in der Xamarin.Forms-Shell

Download Sample Das Beispiel herunterladen

Die Xamarin.Forms-Shell enthält eine URI-basierte Navigationsumgebung, die Routen verwendet, um zu einer beliebigen Seite in der Anwendung zu navigieren, ohne einer festen Navigationshierarchie folgen zu müssen. Darüber hinaus bietet es auch die Möglichkeit, rückwärts zu navigieren, ohne alle Seiten des Navigationsstapels aufrufen zu müssen.

In der Shell-Klasse sind die folgenden Navigationseigenschaften definiert:

Die Eigenschaften BackButtonBehavior, CurrentItem und CurrentState werden durch BindableProperty-Objekte gestützt, was bedeutet, dass diese Eigenschaften Ziele von Datenverbindungen sein können.

Navigation erfolgt durch Aufrufen der GoToAsync-Methode aus der Shell-Klasse. Kurz bevor die Navigation erfolgt, wird ein Navigating-Ereignis ausgelöst, und das Navigated-Ereignis wird ausgelöst, wenn die Navigation abgeschlossen ist.

Hinweis

Die Navigation zwischen Seiten kann in einer Shellanwendung unter Verwendung der Eigenschaft Navigation weiterhin durchgeführt werden. Weitere Informationen finden Sie unter Hierarchische Navigation.

Routen

Die Navigation erfolgt in einer Shell-Anwendung durch Angabe eines URI, zu dem navigiert werden soll. Navigation-URIs können drei Komponenten aufweisen:

  • Eine Route, die den Pfad zu Inhalt definiert, der als Teil der visuellen Shell-Hierarchie vorhanden ist.
  • Eine Seite. Seiten, die in der visuellen Shell-Hierarchie nicht vorhanden sind, können von überall innerhalb einer Shell-Anwendung per Push an den Navigationsstapel übertragen werden. Beispielsweise wird eine Detailseite nicht in der visuellen Shellhierarchie definiert, sondern kann bei Bedarf mithilfe von Push an den Navigationsstapel übertragen werden.
  • Mindestens ein Abfrageparameter. Abfrageparameter sind Parameter, die während der Navigation an die Zielseite übergeben werden können.

Wenn ein Navigations-URI alle drei Komponenten enthält, lautet die Struktur „//route/page?queryParameters“.

Registrieren von Routen

Routen können für FlyoutItem-, TabBar-, Tab- und ShellContent-Objekte über ihre Route-Eigenschaften definiert werden:

<Shell ...>
    <FlyoutItem ...
                Route="animals">
        <Tab ...
             Route="domestic">
            <ShellContent ...
                          Route="cats" />
            <ShellContent ...
                          Route="dogs" />
        </Tab>
        <ShellContent ...
                      Route="monkeys" />
        <ShellContent ...
                      Route="elephants" />  
        <ShellContent ...
                      Route="bears" />
    </FlyoutItem>
    <ShellContent ...
                  Route="about" />                  
    ...
</Shell>

Hinweis

Allen Elementen in der Shell-Hierarchie ist eine Route zugeordnet. Wenn Sie keine Route festlegen, wird zur Laufzeit eine generiert. Die Konsistenz der generierten Routen wird jedoch nicht über verschiedene Anwendungssitzungen hinweg garantiert.

Im obigen Beispiel wird die folgende Routenhierarchie erstellt, die bei der programmgesteuerten Navigation verwendet werden kann:

animals
  domestic
    cats
    dogs
  monkeys
  elephants
  bears
about

Der absolute Routen-URI lautet //animals/domestic/dogs, um zum ShellContent-Objekt für die dogs-Route zu navigieren. Um zum ShellContent-Objekt für die about-Route zu navigieren, lautet der absolute Routen-URI entsprechend //about.

Warnung

Eine ArgumentException wird beim Start der Anwendung ausgelöst, wenn eine doppelte Route erkannt wird. Diese Ausnahme wird auch ausgelöst, wenn mindestens zwei Routen auf derselben Ebene in der Hierarchie einen Routennamen gemeinsam verwenden.

Registrieren von Detailseitenrouten

Im Shell-Unterklassenkonstruktor oder an jedem anderen Ort, der vor dem Aufruf einer Route ausgeführt wird, können zusätzliche Routen explizit für alle Detailseiten registriert werden, die in der visuellen Shellhierarchie nicht repräsentiert werden. Dies wird mit der Routing.RegisterRoute-Methode erreicht:

Routing.RegisterRoute("monkeydetails", typeof(MonkeyDetailPage));
Routing.RegisterRoute("beardetails", typeof(BearDetailPage));
Routing.RegisterRoute("catdetails", typeof(CatDetailPage));
Routing.RegisterRoute("dogdetails", typeof(DogDetailPage));
Routing.RegisterRoute("elephantdetails", typeof(ElephantDetailPage));

In diesem Beispiel werden Detailseiten, die nicht in der Shell-Unterklasse definiert sind, als Routen registriert. Diese Detailseiten können dann von überall in der Anwendung über eine URI-basierte Navigation aufgerufen werden. Die Routen für solche Seiten werden als globale Routen bezeichnet.

Warnung

Eine ArgumentException wird ausgelöst, wenn die Routing.RegisterRoute-Methode versucht, dieselbe Route für mindestens zwei unterschiedliche Typen zu registrieren.

Alternativ können Seiten bei Bedarf bei verschiedenen Routenhierarchien registriert werden:

Routing.RegisterRoute("monkeys/details", typeof(MonkeyDetailPage));
Routing.RegisterRoute("bears/details", typeof(BearDetailPage));
Routing.RegisterRoute("cats/details", typeof(CatDetailPage));
Routing.RegisterRoute("dogs/details", typeof(DogDetailPage));
Routing.RegisterRoute("elephants/details", typeof(ElephantDetailPage));

Dieses Beispiel ermöglicht eine kontextbezogene Seitennavigation, bei der die Navigation zur details-Route von der Seite für die monkeys-Route die MonkeyDetailPage anzeigt. Entsprechend zeigt die Navigation zur details-Route von der Seite für die elephants-Route die ElephantDetailPage an. Weitere Informationen finden Sie unter Kontextbezogene Navigation.

Hinweis

Die Registrierung von Seiten, deren Routen mit der Routing.RegisterRoute-Methode registriert wurden, kann bei Bedarf mit der Routing.UnRegisterRoute-Methode aufgehoben werden.

Durchführen der Navigation

Zuerst muss ein Verweis auf die Unterklasse Shell abgerufen werden, um die Navigation durchzuführen. Dieser Verweis kann durch Umwandeln der App.Current.MainPage-Eigenschaft in ein Shell-Objekt oder über die Shell.Current-Eigenschaft erzielt werden. Die Navigation kann dann durch Aufrufen der GoToAsync-Methode für das Shell-Objekt durchgeführt werden. Diese Methode navigiert zu einem ShellNavigationState und gibt einen Task zurück, der nach Ende der Navigationsanimation abgeschlossen wird. Das ShellNavigationState-Objekt wird durch die GoToAsync-Methode aus einer string oder einem Uri gebildet, und verfügt über eine Location-Eigenschaft, die auf das Argument string oder Uri festgelegt ist.

Wichtig

Erfolgt die Navigation zu einer Route aus der visuellen Shell-Hierarchie, wird kein Navigationsstapel erstellt. Erfolgt die Navigation jedoch zu einer Seite, die sich nicht in der visuellen Shell-Hierarchie befindet, wird kein Navigationsstapel erstellt.

Der aktuelle Navigationsstatus des Shell-Objekts kann über die Shell.Current.CurrentState-Eigenschaft abgerufen werden, die den URI der angezeigten Route in der Location-Eigenschaft enthält.

Absolute Routen

Die Navigation kann durch Angeben eines gültigen absoluten URIs als Argument für die GoToAsync-Methode durchgeführt werden:

await Shell.Current.GoToAsync("//animals/monkeys");

In diesem Beispiel erfolgt die Navigation zur Seite für die monkeys-Route, wobei die Route im ShellContent-Objekt definiert wird. Das ShellContent-Objekt, das die monkeys-Route darstellt, ist ein untergeordnetes Element eines FlyoutItem-Objekts mit der Route animals.

Relative Routen

Die Navigation kann auch durch Angeben eines gültigen relativen URIs als Argument für die GoToAsync-Methode durchgeführt werden. Das Routingsystem versucht daher, den URI mit einem ShellContent-Objekt abzugleichen. Wenn also alle Routen in einer Anwendung eindeutig sind, kann die Navigation durchgeführt werden, indem nur der eindeutige Routenname als relativer URI angegeben wird.

Die folgenden relativen Routenformate werden unterstützt:

Format Beschreibung
route In der Routenhierarchie wird von der aktuellen Position aus nach oben nach der angegebenen Route gesucht. Die übereinstimmende Seite wird per Push an den Navigationsstapel übertragen.
/route In der Routenhierarchie wird von der aktuellen Position aus nach unten nach der angegebenen Route gesucht. Die übereinstimmende Seite wird per Push an den Navigationsstapel übertragen.
//route In der Routenhierarchie wird von der aktuellen Position aus nach oben nach der angegebenen Route gesucht. Die übereinstimmende Seite ersetzt den Navigationsstapel.
///route In der Routenhierarchie wird von der aktuellen Position aus nach unten nach der angegebenen Route gesucht. Die übereinstimmende Seite ersetzt den Navigationsstapel.

Im folgenden Beispiel wird zur Seite für die monkeydetails-Route navigiert:

await Shell.Current.GoToAsync("monkeydetails");

In diesem Beispiel wird die Hierarchie aufwärts nach der monkeyDetails-Route durchsucht, bis die übereinstimmende Seite gefunden wird. Wenn die Seite gefunden wird, wird sie per Push an den Navigationsstapel übertragen.

Kontextbezogene Navigation

Relative Routen ermöglichen kontextbezogene Navigation. Nehmen wir beispielsweise die folgende Routenhierarchie:

monkeys
  details
bears
  details

Wenn die registrierte Seite für die monkeys-Route angezeigt wird, wird durch die Navigation zur details-Route die registrierte Seite für die monkeys/details-Route angezeigt. Wenn die registrierte Seite für die bears-Route angezeigt wird, wird durch die Navigation zur details-Route entsprechend die registrierte Seite für die bears/details-Route angezeigt. Informationen zum Registrieren der Routen in diesem Beispiel finden Sie unter Registrieren von Seitenrouten.

Rückwärtsnavigation

Die Rückwärtsnavigation kann erfolgen, indem Sie ".." als Argument zur GoToAsync-Methode hinzufügen.

await Shell.Current.GoToAsync("..");

Die Rückwärtsnavigation mit ".." kann auch mit einer Route kombiniert werden:

await Shell.Current.GoToAsync("../route");

In diesem Beispiel wird die Rückwärtsnavigation und dann die Navigation zur angegebenen Route durchgeführt.

Wichtig

Die Rückwärtsnavigation und die Navigation zu einer angegebenen Route sind nur möglich, wenn die Rückwärtsnavigation Sie zur aktuellen Position in der Routenhierarchie bringt, damit Sie zur angegebenen Route navigieren können.

Ebenso ist es möglich, mehrmals rückwärts und dann zu einer bestimmten Route zu navigieren:

await Shell.Current.GoToAsync("../../route");

In diesem Beispiel wird zweimal die Rückwärtsnavigation und dann die Navigation zur angegebenen Route durchgeführt.

Darüber hinaus können Daten bei der Rückwärtsnavigation durch Abfrageeigenschaften übergeben werden:

await Shell.Current.GoToAsync($"..?parameterToPassBack={parameterValueToPassBack}");

In diesem Beispiel wird die Rückwärtsnavigation durchgeführt, und der Abfrageparameterwert wird an den Abfrageparameter auf der vorherigen Seite übergeben.

Hinweis

Abfrageparameter können an jede Rückwärtsnavigationsanforderung angehängt werden.

Weitere Informationen zum Übergeben von Daten bei der Navigation finden Sie unter Übergeben von Daten.

Ungültige Routen

Die folgenden Routenformate sind ungültig:

Format Erklärung
//page oder ///page Globale Routen dürfen derzeit nicht die einzige Seite im Navigationsstapel sein. Aus diesem Grund wird das absolute Routing zu globalen Routen nicht unterstützt.

Die Verwendung dieser Routenformate führt dazu, dass eine Exception ausgelöst wird.

Warnung

Der Versuch, zu einer nicht vorhandenen Route zu navigieren führt dazu, dass eine ArgumentException ausgelöst wird.

Debuggen der Navigation

Einige der Shell-Klassen werden mit dem DebuggerDisplayAttribute ergänzt, das festlegt, wie eine Klasse oder das Feld vom Debugger angezeigt wird. Dies kann helfen, Navigationsanforderungen zu debuggen, indem Daten angezeigt werden, die sich auf die Navigationsanforderung beziehen. Der folgende Screenshot zeigt beispielsweise die Eigenschaften CurrentItem und CurrentState des Shell.Current-Objekts an:

Screenshot of debugger

In diesem Beispiel zeigt die CurrentItem-Eigenschaft vom Typ FlyoutItem den Titel und die Route des FlyoutItem-Objekts an. Entsprechend zeigt die CurrentState-Eigenschaft vom Typ ShellNavigationState den URI der angezeigten Route in der Shellanwendung an.

Die Tab-Klasse definiert eine Stack-Eigenschaft vom Typ IReadOnlyList<Page>, die für den aktuellen Navigationsstapel innerhalb des Tab steht. Die Klasse stellt außerdem die folgenden überschreibbaren Navigationsmethoden zur Verfügung:

  • GetNavigationStack, liefert IReadOnlyList<Page>, den aktuellen Navigationsstapel.
  • OnInsertPageBefore: Wird aufgerufen, wenn INavigation.InsertPageBefore aufgerufen wird.
  • OnPopAsync: Gibt Task<Page> zurück, und wird aufgerufen, wenn INavigation.PopAsync aufgerufen wird.
  • OnPopToRootAsync: Gibt Task zurück, und wird aufgerufen, wenn INavigation.OnPopToRootAsync aufgerufen wird.
  • OnPushAsync: Gibt Task zurück, und wird aufgerufen, wenn INavigation.PushAsync aufgerufen wird.
  • OnRemovePage: Wird aufgerufen, wenn INavigation.RemovePage aufgerufen wird.

Im folgenden Beispiel sehen Sie, wie die OnRemovePage-Methode überschrieben wird:

public class MyTab : Tab
{
    protected override void OnRemovePage(Page page)
    {
        base.OnRemovePage(page);

        // Custom logic
    }
}

In diesem Beispiel sollten in Ihrer visuellen Shellhierarchie MyTab-Objekte anstelle von Tab-Objekten verwendet werden.

Die Shell-Klasse definiert das Navigating-Ereignis, das ausgelöst wird, kurz bevor die Navigation entweder aufgrund von programmgesteuerter Navigation oder Benutzerinteraktion erfolgt. Das ShellNavigatingEventArgs-Objekt, das das Navigating-Ereignis begleitet, stellt die folgenden Eigenschaften bereit:

Eigenschaft Typ Beschreibung
Current ShellNavigationState Der URI der aktuellen Seite.
Source ShellNavigationSource Der Typ der erfolgten Navigation.
Target ShellNavigationState Der URI, der darstellt, wohin die Navigation führt.
CanCancel bool Ein Wert, der angibt, ob ein Abbruch der Navigation möglich ist.
Cancelled bool Ein Wert, der angibt, ob die Navigation abgebrochen wurde.

Außerdem stellt die ShellNavigatingEventArgs-Klasse eine Cancel-Methode bereit, die verwendet werden kann, um die Navigation abzubrechen. Zusätzlich stellt sie eine GetDeferral-Methode bereit, die ein ShellNavigatingDeferral-Token zurückgibt, das verwendet werden kann, um die Navigation abzuschließen. Weitere Informationen zur Navigationsverzögerung finden Sie unter Navigationsverzögerung.

Die Shell-Klasse definiert außerdem ein Navigated-Ereignis, das ausgelöst wird, wenn die Navigation abgeschlossen ist. Das ShellNavigatedEventArgs-Objekt, das das Navigated-Ereignis begleitet, stellt die folgenden Eigenschaften bereit:

Eigenschaft Typ Beschreibung
Current ShellNavigationState Der URI der aktuellen Seite.
Previous ShellNavigationState Der URI der vorherigen Seite.
Source ShellNavigationSource Der Typ der erfolgten Navigation.

Wichtig

Die OnNavigating-Methode wird aufgerufen, wenn das Navigating-Ereignis ausgelöst wird. Ebenso wird die OnNavigated-Methode aufgerufen, wenn das Navigated-Ereignis ausgelöst wird. Beide Methoden können in der Shell-Unterklasse überschrieben werden, um Navigationsanforderungen abzufangen.

Die Klassen ShellNavigatedEventArgs und ShellNavigatingEventArgs verfügen beide über Source-Eigenschaften vom Typ ShellNavigationSource. Diese Enumeration stellt die folgenden Werte bereit:

  • Unknown
  • Push
  • Pop
  • PopToRoot
  • Insert
  • Remove
  • ShellItemChanged
  • ShellSectionChanged
  • ShellContentChanged

Aus diesem Grund kann die Navigation in einer OnNavigating-Überschreibung abgefangen werden, und Aktionen können basierend auf der Navigationsressource ausgeführt werden. Der folgende Code zeigt beispielsweise, wie die Rückwärtsnavigation abgebrochen wird, wenn die Daten auf der Seite nicht gespeichert wurden:

protected override void OnNavigating(ShellNavigatingEventArgs args)
{
    base.OnNavigating(args);

    // Cancel any back navigation.
    if (args.Source == ShellNavigationSource.Pop)
    {
        args.Cancel();
    }
// }

Die Shellnavigation kann basierend auf der Benutzerauswahl abgefangen und abgeschlossen oder abgebrochen werden. Dies kann erreicht werden, indem Sie die OnNavigating-Methode in Ihrer Shell-Unterklasse überschreiben und die GetDeferral-Methode für das ShellNavigatingEventArgs-Objekt aufrufen. Diese Methode gibt ein ShellNavigatingDeferral-Token zurück, das über eine Complete-Methode verfügt, die zum Vervollständigen der Navigationsanforderung verwendet werden kann:

public MyShell : Shell
{
    // ...
    protected override async void OnNavigating(ShellNavigatingEventArgs args)
    {
        base.OnNavigating(args);

        ShellNavigatingDeferral token = args.GetDeferral();

        var result = await DisplayActionSheet("Navigate?", "Cancel", "Yes", "No");
        if (result != "Yes")
        {
            args.Cancel();
        }
        token.Complete();
    }    
}

In diesem Beispiel wird ein Aktionsblatt angezeigt, in dem der Benutzer aufgefordert wird, die Navigationsanforderung abzuschließen oder abzubrechen. Die Navigation wird abgebrochen, indem die Cancel-Methode für das ShellNavigatingEventArgs-Objekt aufgerufen wird. Die Navigation wird durch Aufrufen der Complete-Methode für das ShellNavigatingDeferral-Token abgeschlossen, das von der GetDeferral-Methode für das ShellNavigatingEventArgs-Objekt abgerufen wurde.

Warnung

Durch die GoToAsync-Methode wird eine InvalidOperationException ausgelöst, wenn ein Benutzer versucht, zu navigieren, während eine ausstehende Navigationsverzögerung vorliegt.

Übergeben von Daten

Daten können als Abfrageparameter übergeben werden, wenn eine URI-basierte, programmgesteuerte Navigation ausgeführt wird. Dies wird erreicht, indem nach einer Route ? angehängt wird, gefolgt von einer Abfrageparameter-ID (=) und einem Wert. Der folgende Code wird beispielsweise in der Beispielanwendung ausgeführt, wenn ein Benutzer einen Elefanten auf der ElephantsPage auswählt:

async void OnCollectionViewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    string elephantName = (e.CurrentSelection.FirstOrDefault() as Animal).Name;
    await Shell.Current.GoToAsync($"elephantdetails?name={elephantName}");
}

Dieses Codebeispiel ruft den aktuell ausgewählten Elefanten in der elephantdetails ab, und navigiert zur CollectionView-Route, wobei elephantName als Abfrageparameter übergeben wird.

Es gibt zwei Ansätze zum Empfangen von Navigationsdaten:

  1. Die Klasse, die die Seite darstellt, zu der navigiert wird, oder die Klasse für den BindingContext der Seite kann um ein QueryPropertyAttribute für jeden Abfrageparameter ergänzt werden. Weitere Informationen finden Sie unter Verarbeiten von Navigationsdaten mithilfe von Abfrageeigenschaftsattributen.
  2. Die Klasse, die die Seite darstellt, zu der navigiert wird, oder die Klasse für den BindingContext der Seite kann die IQueryAttributable-Schnittstelle implementieren. Weitere Informationen finden Sie unter Verarbeiten von Navigationsdaten mit einer einzelnen Methode.

Verarbeiten von Navigationsdaten mithilfe von Abfrageeigenschaftsattributen

Navigationsdaten können empfangen werden, indem die empfangende Klasse mit einem QueryPropertyAttribute für jeden Abfrageparameter ergänzt wird:

[QueryProperty(nameof(Name), "name")]
public partial class ElephantDetailPage : ContentPage
{
    public string Name
    {
        set
        {
            LoadAnimal(value);
        }
    }
    ...

    void LoadAnimal(string name)
    {
        try
        {
            Animal animal = ElephantData.Elephants.FirstOrDefault(a => a.Name == name);
            BindingContext = animal;
        }
        catch (Exception)
        {
            Console.WriteLine("Failed to load animal.");
        }
    }    
}

Das erste Argument für das QueryPropertyAttribute gibt den Namen der Eigenschaft, die die Daten empfangen soll, und das zweite Argument die ID des Abfrageparameters an. Das QueryPropertyAttribute im oben stehenden Beispiel legt somit fest, dass die Name-Eigenschaft die im name-Abfrageparameter übergebenen Daten vom URI im GoToAsync-Methodenaufruf erhält. Der Name-Eigenschaftensetter ruft die LoadAnimal-Methode auf, um das Animal-Objekt für den name abzurufen, und sendet diesen als BindingContext der Seite.

Hinweis

Abfrageparameterwerte, die über QueryPropertyAttribute empfangen werden, werden automatisch URL-decodiert.

Verarbeiten von Navigationsdaten mit einer einzelnen Methode

Navigationsdaten können empfangen werden, indem die IQueryAttributable-Schnittstelle für die empfangende Klasse implementiert wird. Die IQueryAttributable-Schnittstelle gibt an, dass die implementierende Klasse die ApplyQueryAttributes-Methode implementieren muss. Diese Methode verfügt über ein query-Argument vom Typ IDictionary<string, string>, das alle während der Navigation übergebenen Daten enthält. Jeder Schlüssel im Wörterbuch ist eine Abfrageparameter-ID, und der Wert ist der Wert des Abfrageparameters. Der Vorteil dieser Vorgehensweise besteht darin, dass Navigationsdaten mit einer einzigen Methode verarbeitet werden können. Dies kann hilfreich sein, wenn Sie über mehrere Navigationsdatenelemente verfügen, die als Ganzes verarbeitet werden müssen.

Das folgende Beispiel veranschaulicht eine Ansichtsmodellklasse, die die IQueryAttributable-Schnittstelle implementiert:

public class MonkeyDetailViewModel : IQueryAttributable, INotifyPropertyChanged
{
    public Animal Monkey { get; private set; }

    public void ApplyQueryAttributes(IDictionary<string, string> query)
    {
        // The query parameter requires URL decoding.
        string name = HttpUtility.UrlDecode(query["name"]);
        LoadAnimal(name);
    }

    void LoadAnimal(string name)
    {
        try
        {
            Monkey = MonkeyData.Monkeys.FirstOrDefault(a => a.Name == name);
            OnPropertyChanged("Monkey");
        }
        catch (Exception)
        {
            Console.WriteLine("Failed to load animal.");
        }
    }
    ...
}

In diesem Beispiel ruft die ApplyQueryAttributes-Methode den Wert des name-Abfrageparameters aus dem URI im GoToAsync-Methodenaufruf ab. Anschließend wird die LoadAnimal-Methode aufgerufen, um das Animal-Objekt abzurufen, wobei es als Wert der Monkey-Eigenschaft festgelegt wird, an die Daten gebunden sind.

Wichtig

Abfrageparameterwerte, die über die IQueryAttributable-Schnittstelle empfangen werden, werden nicht automatisch URL-decodiert.

Übergeben und Verarbeiten mehrerer Abfrageparameter

Mehrere Abfrageparameter können übergeben werden, indem sie durch & verbunden werden. Der folgende Code übergibt beispielsweise zwei Datenelemente:

async void OnCollectionViewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    string elephantName = (e.CurrentSelection.FirstOrDefault() as Animal).Name;
    string elephantLocation = (e.CurrentSelection.FirstOrDefault() as Animal).Location;
    await Shell.Current.GoToAsync($"elephantdetails?name={elephantName}&location={elephantLocation}");
}

Dieses Codebeispiel ruft den aktuell ausgewählten Elefanten in der CollectionView ab und navigiert zur elephantdetails-Route, wobei elephantName und elephantLocation als Abfrageparameter übergeben werden.

Damit Sie mehrere Datenelemente empfangen können, kann die Klasse, die die Seite darstellt, zu der navigiert wird, oder die Klasse für den BindingContext der Seite um ein QueryPropertyAttribute für jeden Abfrageparameter ergänzt werden:

[QueryProperty(nameof(Name), "name")]
[QueryProperty(nameof(Location), "location")]
public partial class ElephantDetailPage : ContentPage
{
    public string Name
    {
        set
        {
            // Custom logic
        }
    }

    public string Location
    {
        set
        {
            // Custom logic
        }
    }
    ...    
}

In diesem Beispiel wird die Klasse mit einem QueryPropertyAttribute für jeden Abfrageparameter ergänzt. Das erste QueryPropertyAttribute gibt an, dass die Name-Eigenschaft die Daten empfängt, die im name-Abfrageparameter übergeben werden. Das zweite QueryPropertyAttribute gibt an, dass die Location-Eigenschaft die Daten empfängt, die im location-Abfrageparameter übergeben werden. In beiden Fällen werden die Abfrageparameterwerte im URI im GoToAsync-Methodenaufruf angegeben.

Alternativ können Navigationsdaten von einer einzelnen Methode verarbeitet werden, indem die IQueryAttributable-Schnittstelle für die Klasse implementiert wird, die die Seite darstellt, zu der navigiert wird, oder für die Klasse für den BindingContext der Seite:

public class ElephantDetailViewModel : IQueryAttributable, INotifyPropertyChanged
{
    public Animal Elephant { get; private set; }

    public void ApplyQueryAttributes(IDictionary<string, string> query)
    {
        string name = HttpUtility.UrlDecode(query["name"]);
        string location = HttpUtility.UrlDecode(query["location"]);
        ...        
    }
    ...
}

In diesem Beispiel ruft die ApplyQueryAttributes-Methode den Wert der Abfrageparameter name und location aus dem URI im GoToAsync-Methodenaufruf ab.

Verhalten der Zurück-Schaltfläche

Die Darstellung und das Verhalten der ZURÜCK-TASTE kann neu definiert werden, indem die angefügte Eigenschaft BackButtonBehavior auf ein BackButtonBehavior-Objekt festgelegt wird. Die BackButtonBehavior-Klasse definiert die folgenden Eigenschaften:

  • Command, vom Typ ICommand: wird ausgeführt, wenn die ZURÜCK-TASTE gedrückt wird.
  • CommandParameter, vom Typ object: Parameter, der an den Command übergeben wird.
  • IconOverride, vom Typ ImageSource: Symbol für die ZURÜCK-TASTE.
  • IsEnabled, vom Typ boolean: gibt an, ob die ZURÜCK-TASTE aktiviert ist. Der Standardwert ist true.
  • TextOverride, vom Typ string: Text, der für die ZURÜCK-TASTE verwendet wird.

Alle diese Eigenschaften werden durch BindableProperty-Objekte gestützt, was bedeutet, dass die Eigenschaften Ziele von Datenverbindungen sein können.

Der folgende Code zeigt ein Beispiel für das erneute Definieren der Darstellung und des Verhaltens der ZURÜCK-TASTE.

<ContentPage ...>    
    <Shell.BackButtonBehavior>
        <BackButtonBehavior Command="{Binding BackCommand}"
                            IconOverride="back.png" />   
    </Shell.BackButtonBehavior>
    ...
</ContentPage>

Der entsprechende C#-Code lautet:

Shell.SetBackButtonBehavior(this, new BackButtonBehavior
{
    Command = new Command(() =>
    {
        ...
    }),
    IconOverride = "back.png"
});

Die Command-Eigenschaft wird auf einen ICommand festgelegt, der ausgeführt wird, wenn die ZURÜCK-TASTE gedrückt wird, und die IconOverride-Eigenschaft wird auf das Symbol festgelegt, das für die ZURÜCK-TASTE verwendet wird:

Screenshot of a Shell back button icon override, on iOS and Android