Hierarchische Navigation

Beispiel herunterladen Das Beispiel herunterladen

Die NavigationPage-Klasse stellt eine hierarchische Navigation bereit, bei welcher der Benutzer wie gewünscht in der Vorwärts- und in der Rückwärtsrichtung durch Seiten navigieren kann. Die Klasse implementiert die Navigation als LIFO-Stapel (Last-In-First-out) von Page-Objekten. In diesem Artikel wird gezeigt, wie die NavigationPage-Klasse verwendet werden kann, um die Navigation in einem Stapel von Seiten auszuführen.

Für den Wechsel von einer auf die andere Seite überträgt eine Anwendung, wie im folgenden Diagramm dargestellt, eine neue Seite mithilfe von Push in den Navigationsstapel, wo sie dann zur aktiven Seite wird:

Pushen einer Seite in den Navigationsstapel

Um zu vorherigen Seite zurückzukehren, entfernt die Anwendung die aktuelle Seite per Pop aus dem Navigationsstapel, und die neue oberste Seite wird zur aktiven Seite. Dieser Vorgang wird in dem folgenden Diagramm veranschaulicht:

Poppen einer Seite aus dem Navigationsstapel

Navigationsmethoden werden von der Eigenschaft Navigation für einen beliebigen Page-Typ verfügbar gemacht. Diese Methoden bieten die Möglichkeit, Seiten per Push auf den Navigationsstapel zu übertragen, Seiten per Pop aus dem Navigationsstapel zu entfernen und die Stapelbearbeitung durchzuführen.

Ausführen der Navigation

Bei der hierarchischen Navigation wird die NavigationPage-Klasse verwendet, um durch einen Stapel von ContentPage-Objekten zu navigieren. Auf den folgenden Screenshots werden die Komponenten der NavigationPage auf den jeweiligen Plattformen veranschaulicht:

NavigationPage-Komponenten

Das Layout einer NavigationPage-Klasse ist plattformabhängig:

  • Unter iOS finden Sie die Navigationsleiste ebenfalls am oberen Rand der Seite, wo ein Titel zu sehen ist. Dort befindet sich auch eine Schaltfläche Zurück, mit der zurück zur vorherigen Seite navigiert werden kann.
  • Unter Android finden Sie die Navigationsleiste ebenfalls am oberen Rand der Seite, wo ein Titel sowie ein Symbol zu sehen. Dort befindet sich auch eine Schaltfläche Zurück, mit der zurück zur vorherigen Seite navigiert werden kann. Das Symbol wird im [Activity]-Attribut definiert, das die MainActivity-Klasse im plattformspezifischen Android-Projekt ergänzt.
  • Auf der Universellen Windows-Plattform wird auf der Navigationsleiste ganz oben auf der Seite ein Titel angezeigt.

Auf allen Plattformen wird der Wert der Page.Title-Eigenschaft als Seitentitel angezeigt. Außerdem kann die IconColor-Eigenschaft auf eine Color-Eigenschaft festgelegt werden, die auf das Symbol in der Navigationsleiste angewendet wird.

Hinweis

Es wird empfohlen, die NavigationPage-Klasse nur mit ContentPage-Instanzen aufzufüllen.

Erstellen der Stammseite

Die erste Seite, die zu einem Navigationsstapel hinzugefügt wird, wird als Stammseite der Anwendung bezeichnet. Das folgende Codebeispiel zeigt, wie dies erreicht wird:

public App ()
{
  MainPage = new NavigationPage (new Page1Xaml ());
}

Dies bewirkt, dass die Page1XamlContentPage instance auf den Navigationsstapel gepusht wird, wo sie zur aktiven Seite und zur Stammseite der Anwendung wird. Dies wird im folgenden Screenshot veranschaulicht:

Stammseite des Navigationsstapels

Hinweis

Die RootPage-Eigenschaft einer NavigationPage-Instanz ermöglicht den Zugriff auf die erste Seite im Navigationsstapel.

Pushen von Seiten auf den Navigationsstapel

Für die Navigation zur Page2Xaml muss die PushAsync-Methode für die Eigenschaft Navigation der aktuellen Seite aufgerufen werden. Dies wird im folgenden Codebeispiel veranschaulicht:

async void OnNextPageButtonClicked (object sender, EventArgs e)
{
  await Navigation.PushAsync (new Page2Xaml ());
}

Dies bewirkt, dass die Page2Xaml-Instanz mithilfe von Push auf den Navigationsstapel übertragen wird, wo sie dann zur aktiven Seite wird. Dies wird im folgenden Screenshot veranschaulicht:

Seite wird in den Navigationsstapel gepusht

Wenn die Methode PushAsync aufgerufen wird, treten die folgenden Ereignisse auf:

  • Bei der Seite, die PushAsync aufruft, wird OnDisappearing überschrieben.
  • Bei der Seite, zu der navigiert wird, wird die Überschreibung von OnAppearing aufgerufen.
  • Aufgabe PushAsync wird abgeschlossen.

Die genaue Reihenfolge, in der diese Ereignisse auftreten, ist jedoch plattformabhängig. Weitere Informationen hierzu finden Sie in Kapitel 24 im Xamarin.Forms-Buch von Charles Petzold.

Hinweis

Aufrufe von Überschreibungen von OnDisappearing und OnAppearing können nicht als garantierte Anzeichen für eine Seitennavigation behandelt werden. Unter iOS beispielsweise wird die Überschreibung von OnDisappearing auf der aktiven Seite aufgerufen, wenn die Anwendung beendet wird.

Eine Seite per Pop aus dem Navigationsstapel entfernen

Die aktive Seite kann durch Drücken der Schaltfläche Zurück an dem Gerät per Pop von dem Navigationsstapel entfernt werden, und zwar unabhängig davon, ob es sich um eine physische Schaltfläche an dem Gerät oder um eine Schaltfläche auf dem Bildschirm handelt.

Wenn Sie programmgesteuert zur ursprünglichen Seite zurückkehren möchten, muss die Page2Xaml-Instanz die PopAsync-Methode aufrufen. Dies wird im folgenden Codebeispiel veranschaulicht:

async void OnPreviousPageButtonClicked (object sender, EventArgs e)
{
  await Navigation.PopAsync ();
}

Dadurch wird die Page2Xaml-Instanz von dem Navigationsstapel entfernt, und die neue oberste Seite wird zur aktiven Seite. Wenn die Methode PopAsync aufgerufen wird, treten die folgenden Ereignisse auf:

  • Bei der Seite, die PopAsync aufruft, wird OnDisappearing überschrieben.
  • Für die Seite, die zurückgegeben wird, wird die Überschreibung von OnAppearing aufgerufen.
  • Die PopAsync-Aufgabe wird zurückgegeben.

Die genaue Reihenfolge, in der diese Ereignisse auftreten, ist jedoch plattformabhängig. Weitere Informationen hierzu finden Sie in Kapitel 24 im Xamarin.Forms-Buch von Charles Petzold.

Die Eigenschaft jeder Seite stellt zusätzlich zu den PushAsync- und NavigationPopAsync-Methoden eine PopToRootAsync-Methode bereit, wie im folgenden Codebeispiel dargestellt:

async void OnRootPageButtonClicked (object sender, EventArgs e)
{
  await Navigation.PopToRootAsync ();
}

Diese Methode entfernt alle Klassen außer die Page-Klasse aus dem Navigationsstapel, deshalb wird die Stammseite der Anwendung zur aktiven Seite.

Animieren von Seitenübergängen

Die Eigenschaft Navigation jeder Seite bietet auch überschriebene Push- und Pop-Methoden, die einen boolean-Parameter beinhalten, der steuert, ob eine Seitenanimation während des Navigierens angezeigt wird. Dies wird im folgenden Codebeispiel veranschaulicht:

async void OnNextPageButtonClicked (object sender, EventArgs e)
{
  // Page appearance not animated
  await Navigation.PushAsync (new Page2Xaml (), false);
}

async void OnPreviousPageButtonClicked (object sender, EventArgs e)
{
  // Page appearance not animated
  await Navigation.PopAsync (false);
}

async void OnRootPageButtonClicked (object sender, EventArgs e)
{
  // Page appearance not animated
  await Navigation.PopToRootAsync (false);
}

Wird der boolean-Parameter auf false festgelegt, wird die Seitenübergangsanimation deaktiviert. Wird der Parameter auf true festgelegt, wird die Seitenübergangsanimation aktiviert. Vorausgesetzt sie wird von der zugrunde liegenden Plattform unterstützt. Bei Push- und Pop-Methoden ohne diesen Parameter wird die Animation standardmäßig aktiviert.

Übergeben von Daten beim Navigieren

Beim Navigieren kann es manchmal erforderlich sein, dass Daten an eine andere Seite übergeben werden. Dies kann auf zwei Arten erfolgen: Durch das Übergeben von Daten durch einen Seitenkonstruktor oder durch Festlegen des BindingContext der neuen Seite auf die Daten. Beide werden nun nacheinander erläutert.

Übergeben von Daten durch einen Seitenkonstruktor

Die einfachste Art, beim Navigieren Daten an eine andere Seite zu übergeben, ist die Verwendung eines Seitenkonstruktors. Dies wird in dem folgenden Codebeispiel gezeigt:

public App ()
{
  MainPage = new NavigationPage (new MainPage (DateTime.Now.ToString ("u")));
}

Dieser Code erstellt eine MainPage-Instanz, mit Angabe von aktuellem Datum und aktueller Uhrzeit im ISO8601-Format, das in einer NavigationPage-Instanz umschlossen ist.

Die MainPage-Instanz empfängt die Daten durch einen Konstruktorparameter wie in dem folgenden Codebeispiel gezeigt:

public MainPage (string date)
{
  InitializeComponent ();
  dateLabel.Text = date;
}

Durch Festlegen der Label.Text-Eigenschaft werden die Daten, wie in den folgenden Screenshots dargestellt, dann auf der Seite angezeigt:

Daten, die über einen Seitenkonstruktor übergeben werden

Übergeben von Daten mithilfe von BindingContext

Ein alternativer Ansatz zum Übergeben von Daten an eine andere Seite während der Navigation ist das Festlegen des BindingContext der neuen Seite auf die Daten. Dies wird im folgenden Codebeispiel veranschaulicht:

async void OnNavigateButtonClicked (object sender, EventArgs e)
{
  var contact = new Contact {
    Name = "Jane Doe",
    Age = 30,
    Occupation = "Developer",
    Country = "USA"
  };

  var secondPage = new SecondPage ();
  secondPage.BindingContext = contact;
  await Navigation.PushAsync (secondPage);
}

Dieser Code legt den BindingContext der SecondPage-Instanz auf die Contact-Instanz fest und navigiert dann zur SecondPage.

Die SecondPage nutzt dann Datenbindung, um die Contact-Instanzdaten anzuzeigen, wie im folgenden XAML-Codebeispiel zu sehen ist:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="PassingData.SecondPage"
             Title="Second Page">
    <ContentPage.Content>
        <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
            <StackLayout Orientation="Horizontal">
                <Label Text="Name:" HorizontalOptions="FillAndExpand" />
                <Label Text="{Binding Name}" FontSize="Medium" FontAttributes="Bold" />
            </StackLayout>
            ...
            <Button x:Name="navigateButton" Text="Previous Page" Clicked="OnNavigateButtonClicked" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Das folgende Codebeispiel zeigt, wie die Datenbindung in C# ausgeführt werden kann:

public class SecondPageCS : ContentPage
{
  public SecondPageCS ()
  {
    var nameLabel = new Label {
      FontSize = Device.GetNamedSize (NamedSize.Medium, typeof(Label)),
      FontAttributes = FontAttributes.Bold
    };
    nameLabel.SetBinding (Label.TextProperty, "Name");
    ...
    var navigateButton = new Button { Text = "Previous Page" };
    navigateButton.Clicked += OnNavigateButtonClicked;

    Content = new StackLayout {
      HorizontalOptions = LayoutOptions.Center,
      VerticalOptions = LayoutOptions.Center,
      Children = {
        new StackLayout {
          Orientation = StackOrientation.Horizontal,
          Children = {
            new Label{ Text = "Name:", FontSize = Device.GetNamedSize (NamedSize.Medium, typeof(Label)), HorizontalOptions = LayoutOptions.FillAndExpand },
            nameLabel
          }
        },
        ...
        navigateButton
      }
    };
  }

  async void OnNavigateButtonClicked (object sender, EventArgs e)
  {
    await Navigation.PopAsync ();
  }
}

Durch mehrere Label-Steuerelemente werden die Daten, wie in den folgenden Screenshots dargestellt, dann auf der Seite angezeigt:

Daten, die über einen BindingContext übergeben werden

Weitere Informationen zur Datenbindung finden Sie unter Data Binding Basics (Datenbindungsgrundlagen).

Bearbeiten des Navigationsstapels

Die Eigenschaft Navigation macht die Eigenschaft NavigationStack verfügbar, über welche die Seiten im Navigationsstapel abgerufen werden können. Während Xamarin.Forms den Zugriff auf den Navigationsstapel verwaltet, stellt die Navigation-Eigenschaft die Methoden InsertPageBefore und RemovePage zum Bearbeiten des Stapels bereit, indem Seiten eingefügt oder entfernt werden.

Die Methode InsertPageBefore fügt eine angegebene Seite noch vor einer vorhandenen angegebenen Seite in den Navigationsstapel ein, so wie in diesem Diagramm gezeigt:

Einfügen einer Seite in den Navigationsstapel

Im folgenden Diagramm ist dargestellt, wie die RemovePage-Methode die angegebene Seite aus dem Navigationsstapel entfernt:

Entfernen einer Seite aus dem Navigationsstapel

Mit diesen Methoden kann eine benutzerdefinierte Navigation durchgeführt werden, z. B. das Ersetzen einer Anmeldeseite durch eine neue Seite, gefolgt von einer erfolgreichen Anmeldung. Dieses Szenario wird im folgenden Codebeispiel veranschaulicht:

async void OnLoginButtonClicked (object sender, EventArgs e)
{
  ...
  var isValid = AreCredentialsCorrect (user);
  if (isValid) {
    App.IsUserLoggedIn = true;
    Navigation.InsertPageBefore (new MainPage (), this);
    await Navigation.PopAsync ();
  } else {
    // Login failed
  }
}

Vorausgesetzt, dass die Anmeldeinformationen des Benutzers richtig sind, wird die MainPage-Instanz noch vor der aktuellen Seite in den Navigationsstapel eingefügt. Die PopAsync-Methode entfernt daraufhin die aktuelle Seite aus dem Navigationsstapel, und die Instanz MainPage wird zur aktiven Seite.

Anzeigen von Ansichten in der Navigationsleiste

Jeder Xamarin.FormsView kann in der Navigationsleiste eines NavigationPageangezeigt werden. Dafür muss die angefügte NavigationPage.TitleView-Eigenschaft für View festgelegt werden. Die angefügte Eigenschaft kann für eine beliebige Page-Klasse festgelegt werden. Wenn die Page per Push auf eine NavigationPage übertragen wird, respektiert die NavigationPage den Wert der Eigenschaft.

Im folgenden Beispiel, das aus dem Title View-Beispiel (Titelansicht) von Xamarin stammt, wird dargestellt, wie die angefügte NavigationPage.TitleView-Eigenschaft von XAML festgelegt wird:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="NavigationPageTitleView.TitleViewPage">
    <NavigationPage.TitleView>
        <Slider HeightRequest="44" WidthRequest="300" />
    </NavigationPage.TitleView>
    ...
</ContentPage>

Hier der entsprechende C#-Code:

public class TitleViewPage : ContentPage
{
    public TitleViewPage()
    {
        var titleView = new Slider { HeightRequest = 44, WidthRequest = 300 };
        NavigationPage.SetTitleView(this, titleView);
        ...
    }
}

Dies führt dazu, dass eine Slider-Klasse in der Navigationsleiste auf der NavigationPage angezeigt wird:

Slider TitleView

Wichtig

Viele Ansichten werden nicht in der Navigationsleiste angezeigt, es sei denn, die Größe der Ansicht wird mit den Eigenschaften WidthRequest und HeightRequest angegeben. Alternativ kann die Ansicht auch in einer StackLayout-Klasse umschlossen werden, wobei die Eigenschaften HorizontalOptions und VerticalOptions auf die entsprechenden Werte festgelegt sind.

Da die Layout-Klasse von der View-Klasse abgeleitet wird, kann die angefügte TitleView-Eigenschaft festgelegt werden, um eine Layoutklasse anzuzeigen, die mehrere Ansichten enthält. Unter iOS und auf der Universellen Windows-Plattform (UWP) kann die Höhe der Navigationsleiste nicht geändert werden. Wenn die in der Navigationsleiste angezeigte Ansicht also die Standardgröße der Navigationsleiste übersteigt, wird sie abgeschnitten. Die Höhe der Navigationsleiste kann unter Android jedoch geändert werden. Legen Sie dazu die bindbare NavigationPage.BarHeight-Eigenschaft auf die Variable double fest, mit der die neue Höhe dargestellt wird. Weitere Informationen finden Sie unter Setting the Navigation Bar Height on a NavigationPage (Festlegen der Höhe der Navigationsleiste auf eine NavigationPage).

Alternativ können Sie eine erweiterte Navigationsleiste vorschlagen, indem Sie einige Inhaltselemente in die Navigationsleiste platzieren und einige in eine Ansicht am oberen Rand des Seiteninhalts, für den Sie die Farbe entsprechend der Navigationsleiste anpassen. Zusätzlich können Sie unter iOS die Trennlinie und den Schatten am unteren Rand der Navigationsleiste entfernen, indem Sie die bindbare NavigationPage.HideNavigationBarSeparator-Eigenschaft auf true festlegen. Weitere Informationen finden Sie unter Hiding the Navigation Bar Separator on a NavigationPage (Ausblenden der Trennlinie der Navigationsleiste auf eine NavigationPage).

Hinweis

Die BackButtonTitleEigenschaften , Title, TitleIconund TitleView können Werte definieren, die Platz auf der Navigationsleiste einnehmen. Obwohl sich die Größe der Navigationsleiste je nach Plattform und Bildschirmgröße unterscheidet, führt das Festlegen all dieser Eigenschaften zu Konflikten, da nicht genügend Platz vorhanden ist. Versuchen Sie also nicht, eine Kombination dieser Eigenschaften zu nutzen, sondern legen Sie nur die TitleView-Eigenschaft fest, um Ihr gewünschtes Design für die Navigationsleiste zu realisieren.

Einschränkungen

Es gibt mehrere Einschränkungen, die Sie beachten sollten, wenn Sie eine View-Klasse in der Navigationsleiste einer NavigationPage anzeigen:

  • Unter iOS werden Ansichten, die in der Navigationsleiste einer NavigationPage platziert sind, an einer anderen Position angezeigt, je nachdem, ob große Titel erlaubt sind. Weitere Informationen zum Aktivieren großer Titel finden Sie unter Große Titel anzeigen.
  • Unter Android können Ansichten nur in Apps, die app-compat nutzen, in der Navigationsleiste einer NavigationPage platziert werden.
  • Es wird empfohlen, große und komplexe Ansichten wie ListView und TableView in der Navigationsleiste einer NavigationPage zu platzieren.