Implementación del desplazamiento entre dos páginas

Aprende a usar un marco y páginas para habilitar la navegación punto a punto básica en una aplicación.

navegación punto a punto

Casi todas las aplicaciones requieren navegación entre páginas. Incluso una aplicación sencilla con una sola página de contenido normalmente tendrá una página de configuración que requiere navegación. En este artículo se describen los conceptos básicos de cómo agregar un XAML Page a la aplicación y usar un Frame para navegar entre páginas.

Importante

Usamos la plantilla Aplicación vacía de Microsoft Visual Studio para este ejemplo. Hay diferencias en las plantillas para las aplicaciones de SDK de Aplicaciones para Windows/WinUI 3 y las aplicaciones para UWP, así que asegúrate de seleccionar la pestaña correcta para el tipo de aplicación.

1. Creación de una aplicación vacía

Para crear una aplicación en blanco en Visual Studio:

  1. Para configurar el equipo de desarrollo, consulte Instalación de herramientas para el SDK de Aplicaciones para Windows.
  2. En la ventana de inicio de Microsoft Visual Studio, seleccione Crear un nuevo proyecto, O bien, en el menú de Visual Studio, elija Archivo>nuevo>proyecto.
  3. En el cuadro de diálogo Crear un nuevo proyecto filtros desplegables, seleccione C# o C++, Windows y WinUI, respectivamente.
  4. Seleccione la plantilla de proyecto Aplicación vacía, empaquetada (WinUI 3 en escritorio) y haga clic en Siguiente. Esa plantilla crea una aplicación de escritorio con una interfaz de usuario basada en WinUI 3.
  5. En el cuadro Nombre del proyecto , escriba BasicNavigationy haga clic en Crear.
  6. Para ejecutar el programa, elige Depurar>Iniciar depuración en el menú o presiona F5. Compile y ejecute la solución en el equipo de desarrollo para confirmar que la aplicación se ejecuta sin errores. Aparecerá una página vacía.
  7. Para detener la depuración y volver a Visual Studio, sal de la aplicación o haz clic en la opción Detener depuración del menú.
  8. Quite cualquier código de ejemplo que se incluya en la plantilla de los MainWindow.xaml archivos de código subyacente y MainWindow .

Sugerencia

Para obtener más información, consulta Crear tu primer proyecto de WinUI 3 (SDK de Aplicaciones para Windows).

2. Usar un marco para navegar entre páginas

Cuando la aplicación tiene varias páginas, usas un marco para navegar entre ellas. La Frame clase admite varios métodos de navegación, como Navigate, GoBack y GoForward, y propiedades como BackStack, ForwardStack y BackStackDepth.

Al crear un nuevo proyecto de SDK de Aplicaciones para Windows en Visual Studio, la plantilla de proyecto crea una MainWindow clase (de tipo Microsoft.UI.Xaml.Window). Sin embargo, no crea un marco o una página y no proporciona ningún código de navegación.

Para habilitar la navegación entre páginas, agregue como Frame elemento raíz de MainWindow. Puede hacerlo en la invalidación del método Application.OnLaunched en el App.xaml archivo de código subyacente. Abra el App archivo de código subyacente, actualice la OnLaunched invalidación y controle el evento NavigationFailed , como se muestra aquí.

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

En el caso de las aplicaciones con navegación más compleja, normalmente usará navigationView como raíz de MainWindow y colocará como Frame contenido de la vista de navegación. Para obtener más información, consulta Vista de navegación.

El método Navigate se usa para mostrar contenido en este Frame. Aquí, MainPage.xaml se pasa al Navigate método , por lo que el método se carga MainPage en .Frame

Si se produce un error en la navegación a la ventana inicial de la aplicación, se produce un NavigationFailed evento y este código produce una excepción en el controlador de eventos.

3. Agregar páginas básicas

La plantilla Aplicación vacía no crea varias páginas de aplicación automáticamente. Para poder navegar entre páginas, debe agregar algunas páginas a la aplicación.

Para agregar un nuevo elemento a la aplicación:

  1. En Explorador de soluciones, haga clic con el botón derecho en el nodo del BasicNavigation proyecto para abrir el menú contextual.
  2. Elija Agregar>nuevo elemento en el menú contextual.
  3. En el cuadro de diálogo Agregar nuevo elemento , seleccione el nodo WinUI en el panel izquierdo y, después, elija Página vacía (WinUI 3) en el panel central.
  4. En el cuadro Nombre , escriba MainPage y presione el botón Agregar .
  5. Repita los pasos del 1 al 4 para agregar la segunda página, pero en el cuadro Nombre , escriba Page2.

Ahora, estos archivos deben aparecer como parte del BasicNavigation proyecto.

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

Para los proyectos de C++, debe agregar una #include directiva en el archivo de encabezado de cada página que haga referencia a otra página. Para el ejemplo de navegación entre páginas que se presenta aquí, el archivo mainpage.xaml.h contiene #include "Page2.xaml.h", a su vez, page2.xaml.h contiene #include "MainPage.xaml.h".

Las plantillas de página de C++ también incluyen un ejemplo Button y un código de controlador de clics que tendrás que quitar de los archivos XAML y de código subyacente de la página.

Agregar contenido a las páginas

En MainPage.xaml, reemplace el contenido de la página existente por el siguiente contenido:

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

Este XAML agrega:

  • Elemento TextBlock denominado pageTitle con su propiedad Text establecida Main Page en como elemento secundario de la cuadrícula raíz.
  • Elemento HyperlinkButton que se usa para navegar a la página siguiente como elemento secundario de la cuadrícula raíz.

En el MainPage archivo de código subyacente, agregue el código siguiente para controlar el Click evento del HyperlinkButton que agregó para habilitar la navegación a 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>());
}

El elemento MainPage es una subclase de la clase Page. La Page clase tiene una propiedad Frame de solo lectura que obtiene el Frame objeto que contiene .Page Cuando el Click controlador de eventos de en HyperlinkButtonMainPage llama a Frame.Navigate(typeof(Page2)), Frame muestra el contenido de Page2.xaml.

Cada vez que se carga una página en el marco, esa página se agrega como PageStackEntry a backStack o ForwardStack del marco, lo que permite la navegación hacia atrás y el historial.

Ahora, haga lo mismo en Page2.xaml. Reemplace el contenido de la página existente por el siguiente contenido:

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

En el Page2 archivo de código subyacente, agregue el código siguiente para controlar el Click evento de HyperlinkButton para navegar a 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>());
}

Compile y ejecute la aplicación. Haz clic en el vínculo que dice "Haz clic para ir a la página 2". La segunda página que muestra "Página 2" en la parte superior, se debería cargar y mostrar en el marco. Ahora haga clic en el vínculo de la página 2 para volver a la página principal.

4. Pasar información entre páginas

La aplicación ahora navega entre dos páginas, pero realmente no hace nada interesante todavía. A menudo, cuando una aplicación tiene varias páginas, las páginas necesitan compartir información. Ahora pasará información de la primera página a la segunda.

En MainPage.xaml, reemplace el HyperlinkButton elemento que agregó anteriormente por el siguiente StackPanel. Esto agrega una etiqueta TextBlock y un TextBoxname para escribir una cadena de texto.

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

Ahora usará la segunda sobrecarga del Navigate método y pasará el texto del cuadro de texto como segundo parámetro. Esta es la firma de esta Navigate sobrecarga:

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

En el HyperlinkButton_Click controlador de eventos del MainPage archivo de código subyacente, agregue un segundo parámetro al método que hace referencia a Navigate la Text propiedad del name cuadro de texto.

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

En Page2.xaml, reemplace el HyperlinkButton objeto que agregó anteriormente por el siguiente StackPanel. Esto agrega un TextBlock para mostrar la cadena de texto pasada desde MainPage.

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

En el Page2 archivo de código subyacente, agregue el código siguiente para invalidar el OnNavigatedTo método :

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

Ejecute la aplicación, escriba su nombre en el cuadro de texto y, a continuación, haga clic en el vínculo que indica Click to go to page 2.

Cuando el Click evento de HyperlinkButton en MainPage llama Frame.Navigate(typeof(Page2), name.Text)a , la name.Text propiedad se pasa a Page2y el valor de los datos del evento se usa para el mensaje que se muestra en la página.

5. Almacenar en caché una página

El contenido y el estado de la página no se almacenan en caché de manera predeterminada, por lo que si quieres almacenar información en la caché, debes habilitar esta opción en todas las páginas de la aplicación.

En nuestro ejemplo básico punto a punto, al hacer clic en el Click to go to page 1 vínculo de Page2, el TextBox (y cualquier otro campo) de MainPage está establecido en su estado predeterminado. Una manera de solucionar este problema es usar la propiedad NavigationCacheMode para especificar que una página se agregue a la memoria caché de la página del marco.

De forma predeterminada, se crea una nueva instancia de página con sus valores predeterminados cada vez que se produce la navegación. En MainPage.xaml, establezca NavigationCacheModeEnabled en (en la etiqueta de apertura Page ) para almacenar en caché la página y conservar todos los valores de contenido y estado de la página hasta que se supere la memoria caché de páginas del marco. Establece NavigationCacheMode en Required si quieres ignorar los límites de CacheSize, que especifican el número de páginas en el historial de navegación que pueden almacenarse en la caché para el marco. Sin embargo, no olvides que los límites de tamaño de la caché pueden ser esenciales en función de los límites de memoria de un dispositivo.

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

Ahora, al hacer clic de nuevo en la página principal, el nombre que escribió en el cuadro de texto sigue estando ahí.

6. Personalizar animaciones de transición de página

De forma predeterminada, cada página se anima en el marco cuando se produce la navegación. La animación predeterminada es una animación de "entrada" que hace que la página se deslice hacia arriba desde la parte inferior de la ventana. Sin embargo, puedes elegir diferentes opciones de animación que se adapten mejor a la navegación de la aplicación. Por ejemplo, puedes usar una animación de "obtención de detalles" para dar la sensación de que el usuario está profundizando más en la aplicación, o una animación de diapositiva horizontal para dar la sensación de que dos páginas son del mismo nivel. Para obtener más información, consulta Transiciones de página.

Estas animaciones se representan mediante sub clases de NavigationTransitionInfo. Para especificar la animación que se va a usar para una transición de página, usará la tercera sobrecarga del Navigate método y pasará una NavigationTransitionInfo subclase como tercer parámetro (infoOverride). Esta es la firma de esta Navigate sobrecarga:

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

En el HyperlinkButton_Click controlador de eventos del MainPage archivo de código subyacente, agregue un tercer parámetro al Navigate método que establece el infoOverride parámetro en slideNavigationTransitionInfo con su propiedad Effect establecida en 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);
}

En el HyperlinkButton_Click controlador de eventos del Page2 archivo de código subyacente, establezca el infoOverride parámetro en slideNavigationTransitionInfo con su propiedad Effect establecida en 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);
}

Ahora, al navegar entre páginas, las páginas se deslizan a la izquierda y a la derecha, lo que proporciona una sensación más natural para esta transición y refuerza la conexión entre las páginas.