Implementare lo spostamento tra due pagine

Scopri come usare un frame e le pagine per abilitare lo spostamento peer-to-peer di base nell'app.

peer to peer navigation

Quasi ogni app richiede lo spostamento tra le pagine. Anche un'app semplice con una singola pagina di contenuto avrà in genere una pagina di impostazioni che richiede la navigazione. In questo articolo vengono descritti i concetti di base dell'aggiunta di un codice XAML Page all'app e l'uso di un Frame oggetto per spostarsi tra le pagine.

Importante

Per questo esempio viene usato il modello App vuota di Microsoft Visual Studio. Esistono differenze nei modelli per le app SDK per app di Windows/WinUI 3 e le app UWP, quindi assicurati di selezionare la scheda corretta per il tipo di app.

1. Creare un'app vuota

Per creare un'app vuota in Visual Studio:

  1. Per configurare il computer di sviluppo, consultare Installare gli strumenti per Windows App SDK.
  2. Nella finestra iniziale di Microsoft Visual Studio selezionare Crea un nuovo progetto oppure scegliere File>nuovo>progetto dal menu di Visual Studio.
  3. Nella finestra di dialogo Crea un nuovo progetto selezionare C# oppure C++ rispettivamente Windows e WinUI.
  4. Seleziona il modello del progetto Blank App, Packaged (WinUI 3 in Desktop) e fai clic su Avanti. Questo modello crea un'app desktop con un'interfaccia utente basata su WinUI 3.
  5. In Nome progetto, inserire BasicNavigation e fare clic su Crea.
  6. Per eseguire il programma, scegliere Debug>Avvia debug dal menù, oppure premere F5. Compilare ed eseguire la soluzione sul computer di sviluppo per verificare che l'app venga eseguita senza errori. Viene visualizzata una pagina vuota.
  7. Per arrestare il debug e tornare a Visual Studio, chiudi l'app o scegli Arresta debug dal menu.
  8. Rimuovere qualsiasi codice di esempio incluso nel modello dai MainWindow.xaml file code-behind e MainWindow .

Suggerimento

Per altre info, vedi Creare il primo progetto WinUI 3 (SDK per app di Windows).

2. Utilizzare un frame per spostarsi tra le pagine

Quando l'app ha più pagine, usa un frame per spostarsi tra di loro. La Frame classe supporta diversi metodi di spostamento come Navigate, GoBack e GoForward e proprietà come BackStack, ForwardStack e BackStackDepth.

Quando si crea un nuovo progetto SDK per app di Windows in Visual Studio, il modello di progetto crea una MainWindow classe (di tipo Microsoft.UI.Xaml.Window). Tuttavia, non crea un frame o una pagina e non fornisce alcun codice di spostamento.

Per abilitare lo spostamento tra le pagine, aggiungere un Frame oggetto come elemento radice di MainWindow. A tale scopo, è possibile eseguire l'override del metodo Application.OnLaunched nel App.xaml file code-behind. Aprire il App file code-behind, aggiornare l'override OnLaunched e gestire l'evento NavigationFailed , come illustrato di seguito.

// App.xaml.cs

protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
    m_window = new MainWindow();

    // Create a Frame to act as the navigation context and navigate to the first page
    Frame rootFrame = new Frame();
    rootFrame.NavigationFailed += OnNavigationFailed;
    // Navigate to the first page, configuring the new page
    // by passing required information as a navigation parameter
    rootFrame.Navigate(typeof(MainPage), args.Arguments);

    // Place the frame in the current Window
    m_window.Content = rootFrame;
    // Ensure the MainWindow is active
    m_window.Activate();
}

void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
    throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}
// App.xaml.h

// Add after OnLaunched declaration.
void OnNavigationFailed(IInspectable const&, Microsoft::UI::Xaml::Navigation::NavigationFailedEventArgs const&);

///////////////
// App.xaml.cpp

void App::OnLaunched(LaunchActivatedEventArgs const& e)
{
    window = make<MainWindow>();
    Frame rootFrame = Frame();
    rootFrame.NavigationFailed({ this, &App::OnNavigationFailed });
    rootFrame.Navigate(xaml_typename<BasicNavigation::MainPage>(), box_value(e.Arguments()));
    window.Content(rootFrame);
    window.Activate();
}

void App::OnNavigationFailed(IInspectable const&, NavigationFailedEventArgs const& e)
{
    throw hresult_error(E_FAIL, hstring(L"Failed to load Page ") + e.SourcePageType().Name);
}

Nota

Per le app con una struttura di spostamento più complessa, in genere userai navigationView come radice di MainWindow e posiziona un Frame oggetto come contenuto della visualizzazione di spostamento. Per altre informazioni, vedere Navigazione.

Il metodo Navigate viene usato per visualizzare il contenuto in questo Frameoggetto . In questo caso, MainPage.xaml viene passato al Navigate metodo , quindi il metodo viene caricato MainPage in Frame.

Se la navigazione alla finestra iniziale dell'app ha esito negativo, si verifica un NavigationFailed evento e questo codice genera un'eccezione nel gestore eventi.

3. Aggiungere pagine di base

Il modello App vuota non crea automaticamente più pagine dell'app. Prima di poter spostarsi tra le pagine, è necessario aggiungere alcune pagine all'app.

Per aggiungere un nuovo elemento all'app:

  1. In Esplora soluzioni, fare clic con il pulsante destro del mouse sul BasicNavigation progetto FleetManagementClassProject.
  2. Scegli Aggiungi>nuovo elemento dal menu di scelta rapida.
  3. Nella finestra di dialogo Aggiungi nuovo elemento selezionare il nodo WinUI nel riquadro sinistro, quindi scegliere Pagina vuota (WinUI 3) nel riquadro centrale.
  4. Nella casella Nome immettere MainPage e premere il pulsante Aggiungi.
  5. Ripetere i passaggi da 1 a 4 per aggiungere la seconda pagina, ma nella casella Nome immettere Page2.

Questi file dovrebbero ora essere elencati come parte del progetto BasicNavigation.

C# C++
  • MainPage.xaml
  • MainPage.xaml.cs
  • Page2.xaml
  • Page2.xaml.cs
  • MainPage.xaml
  • MainPage.xaml.cpp
  • MainPage.xaml.h
  • Page2.xaml
  • Page2.xaml.cpp
  • Page2.xaml.h

Importante

Per i progetti C++, è necessario aggiungere una #include direttiva nel file di intestazione di ogni pagina che fa riferimento a un'altra pagina. Per l'esempio di spostamento tra pagine presentato qui, il file mainpage.xaml.h contiene #include "Page2.xaml.h"a sua volta page2.xaml.h contiene #include "MainPage.xaml.h".

I modelli di pagina C++ includono anche un esempio Button e un codice del gestore clic che dovrai rimuovere dai file XAML e code-behind per la pagina.

Aggiungere contenuto alle pagine

In MainPage.xaml, sostituisci il contenuto della pagina esistente con il seguente contenuto:

<Grid>
    <TextBlock x:Name="pageTitle" Text="Main Page"
               Margin="16" Style="{StaticResource TitleTextBlockStyle}"/>
    <HyperlinkButton Content="Click to go to page 2"
                     Click="HyperlinkButton_Click"
                     HorizontalAlignment="Center"/>
</Grid>

Questo codice XAML aggiunge:

  • Elemento TextBlock denominato pageTitle con la relativa proprietà Text impostata su Main Page come elemento figlio dell'oggetto Grid radice .
  • Elemento HyperlinkButton utilizzato per passare alla pagina successiva come elemento figlio della griglia radice .

Nel MainPage file code-behind, aggiungere il codice seguente per gestire Click l'evento HyperlinkButton aggiunto per abilitare la navigazione Page2.xaml.

// MainPage.xaml.cs

private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{
    Frame.Navigate(typeof(Page2));
}
// pch.h
// Add this include in pch.h to support winrt::xaml_typename

#include <winrt/Windows.UI.Xaml.Interop.h>

////////////////////
// MainPage.xaml.h

void HyperlinkButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);

////////////////////
// MainPage.xaml.cpp

void winrt::BasicNavigation::implementation::MainPage::HyperlinkButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
{
    Frame().Navigate(winrt::xaml_typename<BasicNavigation::Page2>());
}

MainPage è una sottoclasse della classe Page. La Page classe ha una proprietà Frame di sola lettura che ottiene Frame che contiene Page. Quando il Click gestore eventi di HyperlinkButton in MainPage chiama Frame.Navigate(typeof(Page2)), Frame visualizza il contenuto di Page2.xaml.

Ogni volta che una pagina viene caricata nel frame, viene aggiunta come PageStackEntry all'elemento BackStack o ForwardStack di Frame, consentendo la cronologia di spostamento e lo spostamento indietro.

Eseguire ora la stessa operazione in Page2.xaml. Sostituisci il contenuto della pagina esistente con il seguente contenuto:

<Grid>
    <TextBlock x:Name="pageTitle" Text="Page 2"
               Margin="16" Style="{StaticResource TitleTextBlockStyle}"/>
    <HyperlinkButton Content="Click to go to main page"
                     Click="HyperlinkButton_Click"
                     HorizontalAlignment="Center"/>
</Grid>

Nel Page2 file code-behind, aggiungere il seguente codice per gestire Click l'evento HyperlinkButton per navigare MainPage.xaml.

// Page2.xaml.cs

private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{
    Frame.Navigate(typeof(MainPage));
}
// Page2.xaml.h

void HyperlinkButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);

/////////////////
// Page2.xaml.cpp

void winrt::BasicNavigation::implementation::Page2::HyperlinkButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
{
    Frame().Navigate(winrt::xaml_typename<BasicNavigation::MainPage>());
}

Compilare ed eseguire l'app. Fare clic sul collegamento "Fare clic per passare alla pagina 2". La seconda pagina che indica "Pagina 2" nella parte superiore deve essere caricata e visualizzata nella cornice. Fare clic sul collegamento nella pagina 2 per tornare alla pagina principale.

4. Passare le informazioni tra le pagine

L'app ora si sposta tra due pagine, ma non fa ancora nulla di interessante. Spesso, quando un'app ha più pagine, le pagine devono condividere informazioni. Ora passerai alcune informazioni dalla prima alla seconda pagina.

In MainPage.xaml sostituire l'oggetto HyperlinkButton aggiunto in precedenza con l'oggetto StackPanel seguente . Ciò aggiunge un'etichetta TextBlock e un elemento TextBoxname per l'immissione di una stringa di testo.

<StackPanel VerticalAlignment="Center">
    <TextBlock HorizontalAlignment="Center" Text="Enter your name"/>
    <TextBox HorizontalAlignment="Center" Width="200" x:Name="name"/>
    <HyperlinkButton Content="Click to go to page 2"
                              Click="HyperlinkButton_Click"
                              HorizontalAlignment="Center"/>
</StackPanel>

A questo punto si userà il secondo overload del Navigate metodo e si passerà il testo dalla casella di testo come secondo parametro. Ecco la firma di questo Navigate overload:

public bool Navigate(System.Type sourcePageType, object parameter);
bool Navigate(TypeName const& sourcePageType, IInspectable const& parameter);

Nel HyperlinkButton_Click gestore dell'evento del MainPage file code-behind, aggiungere un secondo parametro al Navigate metodo che fa riferimento alla Text proprietà della name casella di testo.

// MainPage.xaml.cs

private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{
    Frame.Navigate(typeof(Page2), name.Text);
}
// MainPage.xaml.cpp

void winrt::BasicNavigation::implementation::MainPage::HyperlinkButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
{ 
    Frame().Navigate(xaml_typename<BasicNavigation::Page2>(), winrt::box_value(name().Text()));
}

In Page2.xaml sostituire HyperlinkButton aggiunto in precedenza con il seguente StackPanel. Ciò aggiunge TextBlock per la visualizzazione della stringa di testo passata da MainPage.

<StackPanel VerticalAlignment="Center">
    <TextBlock HorizontalAlignment="Center" x:Name="greeting"/>
    <HyperlinkButton Content="Click to go to page 1"
                     Click="HyperlinkButton_Click"
                     HorizontalAlignment="Center"/>
</StackPanel>

Nel Page2 file code-behind, aggiungere il seguente codice per eseguire l'override del metodo OnNavigatedTo:

// Page2.xaml.cs

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    if (e.Parameter is string && !string.IsNullOrWhiteSpace((string)e.Parameter))
    {
        greeting.Text = $"Hello, {e.Parameter.ToString()}";
    }
    else
    {
        greeting.Text = "Hello!";
    }
    base.OnNavigatedTo(e);
}
// Page2.xaml.h

void Page2::OnNavigatedTo(Microsoft::UI::Xaml::Navigation::NavigationEventArgs const& e)
{
	auto propertyValue{ e.Parameter().as<Windows::Foundation::IPropertyValue>() };
	if (propertyValue.Type() == Windows::Foundation::PropertyType::String)
	{
		auto name{ winrt::unbox_value<winrt::hstring>(e.Parameter()) };
		if (!name.empty())
		{
			greeting().Text(L"Hello, " + name);
			__super::OnNavigatedTo(e);
			return;
		}
	}
	greeting().Text(L"Hello!");
	__super::OnNavigatedTo(e);
}

Eseguire l'app, digitare il nome nella casella di testo e quindi fare clic sul collegamento che indica Click to go to page 2.

Quando l'evento Click di HyperlinkButton in MainPage chiama Frame.Navigate(typeof(Page2), name.Text), la proprietà name.Text viene passata a Page2 e il valore dei dati dell'evento viene usato per il messaggio visualizzato nella pagina.

5. Memorizzare nella cache una pagina

Per impostazione predefinita, il contenuto e lo stato delle pagine non vengono memorizzati nella cache: per memorizzare informazioni nella cache, devi abilitare questa funzionalità in ogni pagina dell'app.

Nell'esempio peer-to-peer di base, quando si fa clic sul Click to go to page 1 collegamento in Page2, l'oggetto TextBox (e qualsiasi altro campo) MainPage in viene impostato sullo stato predefinito. Un modo per risolvere questo problema consiste nell'usare la proprietà NavigationCacheMode per specificare che una pagina deve essere aggiunta alla cache delle pagine del frame.

Per impostazione predefinita, viene creata una nuova istanza di pagina con i relativi valori predefiniti ogni volta che si verifica lo spostamento. In MainPage.xamlimpostare su NavigationCacheModeEnabled (nel tag di apertura Page ) per memorizzare nella cache la pagina e conservare tutti i valori di contenuto e stato per la pagina fino a quando non viene superata la cache della pagina per il frame. Imposta NavigationCacheMode su Required se vuoi ignorare i limiti definiti con CacheSize, che specifica il numero di pagine nella cronologia di spostamento che possono essere memorizzate nella cache per il frame. Tieni tuttavia presente che i limiti relativi alle dimensioni della cache potrebbero essere cruciali, a seconda dei limiti di memoria di un dispositivo.

<Page
    x:Class="BasicNavigation.MainPage"
    ...
    mc:Ignorable="d"
    NavigationCacheMode="Enabled">

Ora, quando si fa clic di nuovo sulla pagina principale, il nome immesso nella casella di testo è ancora presente.

6. Personalizzare le animazioni di transizione di pagina

Per impostazione predefinita, ogni pagina viene animata nel frame quando si verifica la navigazione. L'animazione predefinita è un'animazione "entrata" che fa scorrere la pagina verso l'alto dalla parte inferiore della finestra. Tuttavia, puoi scegliere diverse opzioni di animazione che meglio si adattano allo spostamento della tua app. Ad esempio, puoi usare un'animazione "drill-in" per dare la sensazione che l'utente stia andando più in profondità nella tua app o un'animazione diapositiva orizzontale per dare la sensazione che due pagine siano peer. Per altre info, vedi Transizioni di pagina.

Queste animazioni sono rappresentate da sottoclassi di NavigationTransitionInfo. Per specificare l'animazione da usare per una transizione di pagina, userai il terzo overload del Navigate metodo e passerai una NavigationTransitionInfo sottoclasse come terzo parametro (infoOverride). Ecco la firma di questo Navigate overload:

public bool Navigate(System.Type sourcePageType, 
                     object parameter,
                     NavigationTransitionInfo infoOverride);
bool Navigate(TypeName const& sourcePageType, 
              IInspectable const& parameter, 
              NavigationTransitionInfo const& infoOverride);

Nel HyperlinkButton_Click gestore eventi del MainPage file code-behind aggiungere un terzo parametro al Navigate metodo che imposta il infoOverride parametro su slideNavigationTransitionInfo con la relativa proprietà Effect impostata su FromRight.

// MainPage.xaml.cs

private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{
    Frame.Navigate(typeof(Page2), 
                   name.Text,
                   new SlideNavigationTransitionInfo() 
                       { Effect = SlideNavigationTransitionEffect.FromRight});
}
// pch.h

#include <winrt/Microsoft.UI.Xaml.Media.Animation.h>

////////////////////
// MainPage.xaml.cpp

using namespace winrt::Microsoft::UI::Xaml::Media::Animation;

// ...

void winrt::BasicNavigation::implementation::MainPage::HyperlinkButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
{   
    // Create the slide transition and set the transition effect to FromRight.
    SlideNavigationTransitionInfo slideEffect = SlideNavigationTransitionInfo();
    slideEffect.Effect(SlideNavigationTransitionEffect(SlideNavigationTransitionEffect::FromRight));
    Frame().Navigate(winrt::xaml_typename<BasicNavigation::Page2>(),
        		     winrt::box_value(name().Text()),
                     slideEffect);
}

Nel HyperlinkButton_Click gestore eventi del Page2 file code-behind impostare il infoOverride parametro su SlideNavigationTransitionInfo con la relativa proprietà Effect impostata su FromLeft.

// Page2.xaml.cs

private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{
    Frame.Navigate(typeof(MainPage),
                   null,
                   new SlideNavigationTransitionInfo() 
                       { Effect = SlideNavigationTransitionEffect.FromLeft});
}
// Page2.xaml.cpp

using namespace winrt::Microsoft::UI::Xaml::Media::Animation;

// ...

void winrt::BasicNavigation::implementation::MainPage::HyperlinkButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
{   
    // Create the slide transition and set the transition effect to FromLeft.
    SlideNavigationTransitionInfo slideEffect = SlideNavigationTransitionInfo();
    slideEffect.Effect(SlideNavigationTransitionEffect(SlideNavigationTransitionEffect::FromLeft));
    Frame().Navigate(winrt::xaml_typename<BasicNavigation::MainPage>(),
        		     nullptr,
                     slideEffect);
}

Ora, quando si passa da una pagina all'altra, la diapositiva delle pagine verso sinistra e destra, che offre una sensazione più naturale per questa transizione e rafforza la connessione tra le pagine.