Navigazione gerarchicaHierarchical Navigation

Scaricare esempio Scaricare l'esempioDownload Sample Download the sample

La classe NavigationPage offre un'esperienza di navigazione gerarchica in cui l'utente è in grado di scorrere le pagine avanti e indietro in base alle esigenze. La classe implementa la navigazione come stack LIFO (Last-In, First-Out) di oggetti Pagina. Questo articolo illustra come usare la classe NavigationPage per eseguire la navigazione in uno stack di pagine.The NavigationPage class provides a hierarchical navigation experience where the user is able to navigate through pages, forwards and backwards, as desired. The class implements navigation as a last-in, first-out (LIFO) stack of Page objects. This article demonstrates how to use the NavigationPage class to perform navigation in a stack of pages.

Per passare da una pagina all'altra, un'applicazione esegue il push di una nuova pagina nello stack di navigazione, in cui diventa la pagina attiva, come illustrato nel diagramma seguente:To move from one page to another, an application will push a new page onto the navigation stack, where it will become the active page, as shown in the following diagram:

Per tornare alla pagina precedente, l'applicazione preleva la pagina corrente dallo stack di navigazione e la nuova pagina in primo piano diventa la pagina attiva, come illustrato nel diagramma seguente:To return back to the previous page, the application will pop the current page from the navigation stack, and the new topmost page becomes the active page, as shown in the following diagram:

I metodi di navigazione sono esposti dalla proprietà Navigation in qualsiasi tipo di Page derivata.Navigation methods are exposed by the Navigation property on any Page derived types. Questi metodi consentono di eseguire il push di pagine nello stack di navigazione, di prelevare pagine dallo stack di navigazione e di eseguire la manipolazione dello stack.These methods provide the ability to push pages onto the navigation stack, to pop pages from the navigation stack, and to perform stack manipulation.

Esecuzione degli spostamentiPerforming Navigation

Nella navigazione gerarchica la classe NavigationPage viene usata per navigare in uno stack di oggetti ContentPage.In hierarchical navigation, the NavigationPage class is used to navigate through a stack of ContentPage objects. Gli screenshot seguenti illustrano i componenti principali della NavigationPage in ogni piattaforma:The following screenshots show the main components of the NavigationPage on each platform:

Il layout di una NavigationPage dipende dalla piattaforma:The layout of a NavigationPage is dependent on the platform:

  • In iOS è presente una barra di spostamento nella parte superiore della pagina che include un titolo e un pulsante Indietro che consente di tornare alla pagina precedente.On iOS, a navigation bar is present at the top of the page that displays a title, and that has a Back button that returns to the previous page.
  • In Android è presente una barra di spostamento nella parte superiore della pagina che include un titolo, un'icona e un pulsante Indietro che consente di tornare alla pagina precedente.On Android, a navigation bar is present at the top of the page that displays a title, an icon, and a Back button that returns to the previous page. L'icona è definita nell'attributo [Activity] che decora la classe MainActivity nel progetto specifico della piattaforma Android.The icon is defined in the [Activity] attribute that decorates the MainActivity class in the Android platform-specific project.
  • Nella piattaforma UWP (Universal Windows Platform) è presente una barra di spostamento nella parte superiore della pagina che visualizza un titolo.On the Universal Windows Platform, a navigation bar is present at the top of the page that displays a title.

In tutte le piattaforme, il valore della proprietà Page.Title verrà visualizzato come titolo della pagina.On all the platforms, the value of the Page.Title property will be displayed as the page title.

Nota

È consigliabile popolare una NavigationPage solo con istanze di ContentPage.It's recommended that a NavigationPage should be populated with ContentPage instances only.

Creazione della pagina radiceCreating the Root Page

La prima pagina aggiunta a uno stack di navigazione è definita pagina radice dell'applicazione e il codice seguente illustra come viene eseguita questa operazione:The first page added to a navigation stack is referred to as the root page of the application, and the following code example shows how this is accomplished:

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

Di conseguenza l'istanza Page1Xaml ContentPage viene inserita tramite push nello stack di navigazione, in cui diventa la pagina attiva e la pagina radice dell'applicazione.This causes the Page1Xaml ContentPage instance to be pushed onto the navigation stack, where it becomes the active page and the root page of the application. Questo è illustrato negli screenshot seguenti:This is shown in the following screenshots:

Nota

La proprietà RootPage di un'istanza NavigationPage fornisce l'accesso alla prima pagina nello stack di navigazione.The RootPage property of a NavigationPage instance provides access to the first page in the navigation stack.

Eseguire il push delle pagine nello stack di navigazionePushing Pages to the Navigation Stack

Per passare a Page2Xaml è necessario chiamare il metodo PushAsync sulla proprietà Navigation della pagina corrente, come illustrato nell'esempio di codice seguente:To navigate to Page2Xaml, it is necessary to invoke the PushAsync method on the Navigation property of the current page, as demonstrated in the following code example:

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

Di conseguenza l'istanza Page2Xaml viene inserita tramite push nello stack di navigazione, in cui diventa la pagina attiva.This causes the Page2Xaml instance to be pushed onto the navigation stack, where it becomes the active page. Questo è illustrato negli screenshot seguenti:This is shown in the following screenshots:

Quando si richiama il metodo PushAsync, si verificano gli eventi seguenti:When the PushAsync method is invoked, the following events occur:

  • Per la pagina che chiama PushAsync viene richiamato l'override di OnDisappearing.The page calling PushAsync has its OnDisappearing override invoked.
  • Per la pagina di destinazione dello spostamento viene richiamato l'override di OnAppearing.The page being navigated to has its OnAppearing override invoked.
  • L'attività PushAsync viene completata.The PushAsync task completes.

Tuttavia, l'ordine preciso in cui si verificano questi eventi è dipendente dalla piattaforma.However, the precise order in which these events occur is platform dependent. Per altre informazioni, vedere il capitolo 24 del manuale di Xamarin.Forms redatto da Charles Petzold.For more information, see Chapter 24 of Charles Petzold's Xamarin.Forms book.

Nota

Le chiamate degli override di OnDisappearing e OnAppearing non possono essere considerate come indicazioni garantite dell'avvenuto spostamento tra le pagine.Calls to the OnDisappearing and OnAppearing overrides cannot be treated as guaranteed indications of page navigation. Ad esempio, in iOS l'override di OnDisappearing viene chiamato per la pagina attiva quando l'applicazione viene terminata.For example, on iOS, the OnDisappearing override is called on the active page when the application terminates.

Prelievo di pagine dallo stack di navigazionePopping Pages from the Navigation Stack

La pagina attiva può essere prelevata dallo stack di navigazione premendo il pulsante Indietro (fisico o su schermo) del dispositivo.The active page can be popped from the navigation stack by pressing the Back button on the device, regardless of whether this is a physical button on the device or an on-screen button.

Per tornare a livello di codice alla pagina originale, l'istanza Page2Xaml deve chiamare il metodo PopAsync, come illustrato nell'esempio di codice seguente:To programmatically return to the original page, the Page2Xaml instance must invoke the PopAsync method, as demonstrated in the following code example:

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

Di conseguenza l'istanza Page2Xaml viene rimossa dallo stack di navigazione e la nuova pagina in primo piano diventa la pagina attiva.This causes the Page2Xaml instance to be removed from the navigation stack, with the new topmost page becoming the active page. Quando si richiama il metodo PopAsync, si verificano gli eventi seguenti:When the PopAsync method is invoked, the following events occur:

  • Per la pagina che chiama PopAsync viene richiamato l'override di OnDisappearing.The page calling PopAsync has its OnDisappearing override invoked.
  • Per la pagina restituita viene richiamato l'override di OnAppearing.The page being returned to has its OnAppearing override invoked.
  • L'attività PopAsync viene completata.The PopAsync task returns.

Tuttavia, l'ordine preciso in cui si verificano questi eventi è dipendente dalla piattaforma.However, the precise order in which these events occur is platform dependent. Per altre informazioni, vedere il capitolo 24 del manuale di Xamarin.Forms redatto da Charles Petzold.For more information see Chapter 24 of Charles Petzold's Xamarin.Forms book.

Analogamente ai metodi PushAsync e PopAsync, la proprietà Navigation di ogni pagina fornisce anche un metodo PopToRootAsync, che viene visualizzato nell'esempio di codice seguente:As well as PushAsync and PopAsync methods, the Navigation property of each page also provides a PopToRootAsync method, which is shown in the following code example:

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

Questo metodo preleva tutto tranne la radice Page dallo stack di navigazione, rendendo pertanto la pagina radice dell'applicazione la pagina attiva.This method pops all but the root Page off the navigation stack, therefore making the root page of the application the active page.

Animazione delle transizioni di paginaAnimating Page Transitions

La proprietà Navigation di ogni pagina offre anche metodi di push e di prelievo sottoposti a override, che includono un parametro boolean che controlla la visualizzazione di un'animazione di pagina durante gli spostamenti, come illustrato nell'esempio di codice seguente:The Navigation property of each page also provides overridden push and pop methods that include a boolean parameter that controls whether to display a page animation during navigation, as shown in the following code example:

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);
}

L'impostazione del parametro boolean su false disabilita l'animazione per la transizione di pagina, mentre l'impostazione del parametro su true abilita l'animazione per la transizione di pagina, a condizione che sia supportata dalla piattaforma sottostante.Setting the boolean parameter to false disables the page-transition animation, while setting the parameter to true enables the page-transition animation, provided that it is supported by the underlying platform. Tuttavia, i metodi di push e prelievo senza questo parametro abilitano l'animazione per impostazione predefinita.However, the push and pop methods that lack this parameter enable the animation by default.

Passaggio di dati durante gli spostamentiPassing Data when Navigating

In alcuni casi, una pagina deve passare dati a un'altra pagina durante gli spostamenti.Sometimes it's necessary for a page to pass data to another page during navigation. Due tecniche per questa operazione sono il passaggio dei dati tramite un costruttore di pagina e l'impostazione di BindingContext della nuova pagina sui dati.Two techniques for accomplishing this are passing data through a page constructor, and by setting the new page's BindingContext to the data. Di seguito verranno descritti entrambi.Each will now be discussed in turn.

Passaggio dei dati tramite un costruttore di paginaPassing Data through a Page Constructor

La tecnica più semplice per il passaggio di dati a un'altra pagina durante gli spostamenti è tramite un parametro del costruttore di pagina, come illustrato nell'esempio di codice seguente:The simplest technique for passing data to another page during navigation is through a page constructor parameter, which is shown in the following code example:

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

Questo codice crea un'istanza di MainPage, passando la data e l'ora correnti in formato ISO8601, di cui viene eseguito il wrapping in un'istanza della NavigationPage.This code creates a MainPage instance, passing in the current date and time in ISO8601 format, which is wrapped in a NavigationPage instance.

L'istanza di MainPage riceve i dati tramite un parametro del costruttore, come illustrato nell'esempio di codice seguente:The MainPage instance receives the data through a constructor parameter, as shown in the following code example:

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

I dati vengono quindi visualizzati nella pagina impostando la proprietà Label.Text, come illustrato negli screenshot seguenti:The data is then displayed on the page by setting the Label.Text property, as shown in the following screenshots:

Passaggio dei dati tramite BindingContextPassing Data through a BindingContext

Un approccio alternativo per passare dati a un'altra pagina durante gli spostamenti consiste nell'impostare BindingContext della nuova pagina sui dati, come illustrato nell'esempio di codice seguente:An alternative approach for passing data to another page during navigation is by setting the new page's BindingContext to the data, as shown in the following code example:

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);
}

Questo codice imposta BindingContext dell'istanza di SecondPage sull'istanza di Contact e quindi passa a SecondPage.This code sets the BindingContext of the SecondPage instance to the Contact instance, and then navigates to the SecondPage.

SecondPage usa quindi il data binding per visualizzare i dati dell'istanza di Contact, come illustrato nell'esempio di codice XAML seguente:The SecondPage then uses data binding to display the Contact instance data, as shown in the following XAML code example:

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

L'esempio di codice seguente illustra come è possibile implementare il data binding in C#:The following code example shows how the data binding can be accomplished in C#:

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 ();
  }
}

I dati vengono quindi visualizzati nella pagina tramite una serie di controlli Label, come illustrato negli screenshot seguenti:The data is then displayed on the page by a series of Label controls, as shown in the following screenshots:

Per altre informazioni sul data binding, vedere Data Binding Basics (Nozioni di base sul data binding).For more information about data binding, see Data Binding Basics.

Modifica dello stack di navigazioneManipulating the Navigation Stack

La proprietà Navigation espone una proprietà NavigationStack dalla quale è possibile ottenere le pagine nello stack di navigazione.The Navigation property exposes a NavigationStack property from which the pages in the navigation stack can be obtained. Sebbene Xamarin.Forms mantenga l'accesso allo stack di navigazione, la proprietà Navigation fornisce i metodi InsertPageBefore e RemovePage per modificare lo stack mediante l'inserimento o la rimozione di pagine.While Xamarin.Forms maintains access to the navigation stack, the Navigation property provides the InsertPageBefore and RemovePage methods for manipulating the stack by inserting pages or removing them.

Il metodo InsertPageBefore inserisce una pagina specificata nello stack di navigazione prima di una pagina specificata esistente, come illustrato nel diagramma seguente:The InsertPageBefore method inserts a specified page in the navigation stack before an existing specified page, as shown in the following diagram:

Il metodo RemovePage rimuove la pagina specificata dallo stack di navigazione, come illustrato nel diagramma seguente:The RemovePage method removes the specified page from the navigation stack, as shown in the following diagram:

Questi metodi consentono un'esperienza di navigazione personalizzata, come la sostituzione di una pagina di accesso con una nuova pagina, dopo un accesso con esito positivo.These methods enable a custom navigation experience, such as replacing a login page with a new page, following a successful login. Nell'esempio di codice seguente viene illustrato questo scenario:The following code example demonstrates this scenario:

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

A condizione che le credenziali dell'utente siano corrette, l'istanza di MainPage viene inserita nello stack di navigazione prima della pagina corrente.Provided that the user's credentials are correct, the MainPage instance is inserted into the navigation stack before the current page. Il metodo PopAsync rimuove quindi la pagina corrente dallo stack di navigazione e l'istanza di MainPage diventa la pagina attiva.The PopAsync method then removes the current page from the navigation stack, with the MainPage instance becoming the active page.

Visualizzazione delle viste nella barra di spostamentoDisplaying Views in the Navigation Bar

Qualsiasi View Xamarin.Forms può essere visualizzato nella barra di spostamento di una NavigationPage.Any Xamarin.Forms View can be displayed in the navigation bar of a NavigationPage. Questa operazione viene eseguita impostando la proprietà associata NavigationPage.TitleView su una View.This is accomplished by setting the NavigationPage.TitleView attached property to a View. Questa proprietà associata può essere impostata su qualunque Page e quando viene eseguito il push della Page in una NavigationPage, NavigationPage rispetta il valore della proprietà.This attached property can be set on any Page, and when the Page is pushed onto a NavigationPage, the NavigationPage will respect the value of the property.

L'esempio seguente, tratto dall'esempio di visualizzazione del titolo, mostra come impostare la proprietà associata NavigationPage.TitleView da XAML:The following example, taken from the Title View sample, shows how to set the NavigationPage.TitleView attached property from XAML:

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

Questo è il codice C# equivalente:Here is the equivalent C# code:

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

Il risultato è la visualizzazione di Slider nella barra di spostamento sulla NavigationPage:This results in a Slider being displayed in the navigation bar on the NavigationPage:

Dispositivo di scorrimento TitleViewSlider TitleView

Importante

Molte viste non saranno più visualizzate nella barra di spostamento, a meno che non vengano specificate le dimensioni della vista con le proprietà WidthRequest e HeightRequest.Many views won't appear in the navigation bar unless the size of the view is specified with the WidthRequest and HeightRequest properties. In alternativa, può essere eseguito il wrapping della vista in un StackLayout con le proprietà HorizontalOptions e VerticalOptions impostate sui valori appropriati.Alternatively, the view can be wrapped in a StackLayout with the HorizontalOptions and VerticalOptions properties set to appropriate values.

Si noti che, poiché la classe Layout deriva dalla classe View, la proprietà associata TitleView può essere impostata per visualizzare una classe di layout contenente viste multiple.Note that, because the Layout class derives from the View class, the TitleView attached property can be set to display a layout class that contains multiple views. In iOS e nella piattaforma UWP (Universal Windows Platform) non è possibile modificare l'altezza della barra di navigazione, pertanto verrà effettuato il ritaglio se la vista visualizzata nella barra di spostamento sarà superiore alle dimensioni predefinite della barra di spostamento.On iOS and the Universal Windows Platform (UWP), the height of the navigation bar can't be changed, and so clipping will occur if the view displayed in the navigation bar is larger than the default size of the navigation bar. Tuttavia, in Android, l'altezza della barra di spostamento può essere modificata impostando la proprietà associabile NavigationPage.BarHeight per una double che rappresenta la nuova altezza.However, on Android, the height of the navigation bar can be changed by setting the NavigationPage.BarHeight bindable property to a double representing the new height. Per altre informazioni, vedere Setting the Navigation Bar Height on a NavigationPage (Impostazione dell'altezza della barra di spostamento su una NavigationPage).For more information, see Setting the Navigation Bar Height on a NavigationPage.

In alternativa, può essere suggerita una barra di spostamento estesa inserendo alcuni contenuti nella barra di spostamento e altri in una vista nella parte superiore del contenuto della pagina, da associare ai colori della barra di navigazione.Alternatively, an extended navigation bar can be suggested by placing some of the content in the navigation bar, and some in a view at the top of the page content that you color match to the navigation bar. Inoltre, in iOS la linea di separazione e l'ombreggiatura nella parte inferiore della barra di spostamento possono essere rimosse impostando la proprietà associabile NavigationPage.HideNavigationBarSeparator su true.In addition, on iOS the separator line and shadow that's at the bottom of the navigation bar can be removed by setting the NavigationPage.HideNavigationBarSeparator bindable property to true. Per altre informazioni, vedere Hiding the Navigation Bar Separator on a NavigationPage (Nascondere il separatore della barra di spostamento su una NavigationPage).For more information, see Hiding the Navigation Bar Separator on a NavigationPage.

Nota

Le proprietà BackButtonTitle, Title, TitleIcon e TitleView possono definire tutte i valori che occupano spazio nella barra di spostamento.The BackButtonTitle, Title, TitleIcon, and TitleView properties can all define values that occupy space on the navigation bar. Mentre le dimensioni della barra di spostamento variano a seconda della piattaforma e delle dimensioni dello schermo, l'impostazione di tutte queste proprietà provocherà conflitti a causa dello spazio limitato disponibile.While the navigation bar size varies by platform and screen size, setting all of these properties will result in conflicts due to the limited space available. Invece di tentare di usare una combinazione di queste proprietà, è possibile ottenere un design migliore della barra di spostamento desiderata impostando solo la proprietà TitleView.Instead of attempting to use a combination of these properties, you may find that you can better achieve your desired navigation bar design by only setting the TitleView property.

LimitazioniLimitations

Esistono alcune limitazioni da tenere presenti quando si visualizza una View nella barra di spostamento di una NavigationPage:There are a number of limitations to be aware of when displaying a View in the navigation bar of a NavigationPage:

  • In iOS, le viste poste nella barra di spostamento di una NavigationPage vengono visualizzate in una posizione diversa a seconda se sono abilitati i titoli di grandi dimensioni.On iOS, views placed in the navigation bar of a NavigationPage appear in a different position depending on whether large titles are enabled. Per altre informazioni sull'abilitazione di titoli di grandi dimensioni, vedere Displaying Large Titles (Visualizzazione di titoli di grandi dimensioni).For more information about enabling large titles, see Displaying Large Titles.
  • In Android, il posizionamento delle viste nella barra di spostamento di una NavigationPage può essere eseguito solo nelle app che usano la compatibilità delle app.On Android, placing views in the navigation bar of a NavigationPage can only be accomplished in apps that use app-compat.
  • Non è consigliabile posizionare viste grandi e complesse, come ListView e TableView, nella barra di spostamento di una NavigationPage.It's not recommended to place large and complex views, such as ListView and TableView, in the navigation bar of a NavigationPage.