Implementar a navegação entre duas páginas

Saiba como usar um quadro e páginas para habilitar a navegação básica ponto a ponto no aplicativo.

navegação ponto a ponto

Quase todos os aplicativos exigem navegação entre páginas. Até mesmo um aplicativo simples com uma única página de conteúdo normalmente terá uma página de configurações que requer navegação. Neste artigo, explicamos os conceitos básicos de como adicionar um XAML Page ao seu aplicativo e usar um Frame para navegar entre páginas.

Importante

Usamos o modelo aplicativo em branco do Microsoft Visual Studio para este exemplo. Há diferenças nos modelos para aplicativos SDK do Aplicativo Windows/WinUI 3 e aplicativos UWP, portanto, selecione a guia correta para o tipo de aplicativo.

1. Crie um aplicativo em branco

Para criar um aplicativo em branco no Visual Studio:

  1. Para configurar o ambiente de desenvolvimento, confira Instalar ferramentas para o SDK do Aplicativo Windows.
  2. Na janela inicial do Microsoft Visual Studio, selecione Criar um novo projeto, OU, no menu do Visual Studio, escolha Arquivo>Novo>Projeto.
  3. Na caixa de diálogo suspensa Criar um novo projeto , selecione C# ou C++, Windows e WinUI, respectivamente.
  4. Selecione o modelo de projeto Aplicativo em Branco, Empacotado (WinUI 3 na Área de Trabalho) e clique em Avançar. Esse modelo cria um aplicativo da área de trabalho com uma interface do usuário baseada na WinUI 3.
  5. Na caixa Nome do projeto , insira BasicNavigatione clique em Criar.
  6. Para executar o programa, escolha Depurar>Iniciar Depuração no menu ou pressione F5. Compile e execute a solução em seu computador de desenvolvimento para confirmar se o aplicativo é executado sem erros. Uma página em branco é exibida.
  7. Para interromper a depuração e retornar ao Visual Studio, saia do aplicativo, ou clique em Parar Depuração no menu.
  8. Remova qualquer código de exemplo incluído no modelo dos MainWindow.xaml arquivos code-behind e MainWindow .

Dica

Para obter mais informações, consulte Criar seu primeiro projeto do WinUI 3 (SDK do Aplicativo Windows).

2. Usar um Quadro para navegar entre páginas

Quando seu aplicativo tiver várias páginas, você usará um Frame para navegar entre elas. A Frame classe dá suporte a vários métodos de navegação, como Navigate, GoBack e GoForward, e propriedades como BackStack, ForwardStack e BackStackDepth.

Quando você cria um novo projeto SDK do Aplicativo Windows no Visual Studio, o modelo de projeto cria uma MainWindow classe (do tipo Microsoft.UI.Xaml.Window). No entanto, ele não cria um Quadro ou Página e não fornece nenhum código de navegação.

Para habilitar a navegação entre páginas, adicione um Frame como o elemento raiz de MainWindow. Você pode fazer isso na substituição do método Application.OnLaunched no App.xaml arquivo code-behind. Abra o App arquivo code-behind, atualize a OnLaunched substituição e manipule o evento NavigationFailed , conforme mostrado aqui.

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

Observação

Para aplicativos com navegação mais complexa, você normalmente usará um NavigationView como a raiz de MainWindow e colocará um Frame como o conteúdo do modo de exibição de navegação. Para obter mais informações, consulte Modo de exibição de navegação.

O método Navigate é usado para exibir conteúdo neste Frame. Aqui, MainPage.xaml é passado para o Navigate método , portanto, o método é MainPage carregado no Frame.

Se a navegação para a janela inicial do aplicativo falhar, ocorrerá um NavigationFailed evento e esse código gerará uma exceção no manipulador de eventos.

3. Adicionar páginas básicas

O modelo aplicativo em branco não cria várias páginas de aplicativo para você. Antes de navegar entre páginas, você precisa adicionar algumas páginas ao seu aplicativo.

Para adicionar um novo item ao seu aplicativo:

  1. Em Gerenciador de Soluções, clique com o botão direito do mouse no nó do BasicNavigation projeto para abrir o menu de contexto.
  2. Escolha Adicionar>Novo Item no menu de contexto.
  3. Na caixa de diálogo Adicionar Novo Item , selecione o nó WinUI no painel esquerdo e escolha Página em Branco (WinUI 3) no painel central.
  4. Na caixa Nome , insira MainPage e pressione o botão Adicionar .
  5. Repita as etapas de 1 a 4 para adicionar a segunda página, mas, na caixa Nome , insira Page2.

Agora, esses arquivos devem ser listados como parte do seu BasicNavigation projeto.

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 projetos C++, você deve adicionar uma #include diretiva no arquivo de cabeçalho de cada página que faz referência a outra página. Para o exemplo de navegação entre páginas apresentado aqui, o arquivo mainpage.xaml.h contém #include "Page2.xaml.h", por sua vez, page2.xaml.h contém #include "MainPage.xaml.h".

Os modelos de página C++ também incluem um exemplo Button e um código de manipulador de cliques que você precisará remover dos arquivos XAML e code-behind da página.

Adicionar conteúdo às páginas

No MainPage.xaml, substitua o conteúdo da página existente pelo seguinte conteúdo:

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

  • Um elemento TextBlock chamado pageTitle com sua propriedade Text definida Main Page como como um elemento filho da Grade raiz.
  • Um elemento HyperlinkButton usado para navegar até a próxima página como um elemento filho da grade raiz.

MainPage No arquivo code-behind, adicione o código a seguir para manipular o Click evento do HyperlinkButton que você adicionou para habilitar a navegação para 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 é uma subclasse da classe Page. A Page classe tem uma propriedade Frame somente leitura que obtém o Frame que contém o Page. Quando o Click manipulador de eventos do HyperlinkButton em MainPage chama Frame.Navigate(typeof(Page2)), o Frame exibe o conteúdo de Page2.xaml.

Sempre que uma página é carregada no quadro, essa página é adicionada como um PageStackEntry ao BackStack ou ForwardStack do Frame, permitindo o histórico e a navegação com versões anteriores.

Agora, faça o mesmo em Page2.xaml. Substitua o conteúdo da página existente pelo seguinte conteúdo:

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

Page2 No arquivo code-behind, adicione o código a seguir para manipular o Click evento do HyperlinkButton para navegar até 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 e execute o aplicativo. Clique no link que diz "Clique para ir à página 2". A segunda página, que diz "Página 2" no topo, deve ser carregada e exibida no quadro. Agora, clique no link na Página 2 para voltar à Página Principal.

4. Passar informações entre páginas

Seu aplicativo agora navega entre duas páginas, mas ainda não faz nada interessante. Geralmente, quando um aplicativo tem várias páginas, as páginas precisam compartilhar informações. Agora você passará algumas informações da primeira página para a segunda página.

Em MainPage.xaml, substitua o HyperlinkButton que você adicionou anteriormente pelo StackPanel a seguir. Isso adiciona um rótulo TextBlock e um TextBoxname para inserir uma cadeia de caracteres 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>

Agora você usará a segunda sobrecarga do Navigate método e passará o texto da caixa de texto como o segundo parâmetro. Esta é a assinatura dessa Navigate sobrecarga:

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

HyperlinkButton_Click No manipulador de eventos do MainPage arquivo code-behind, adicione um segundo parâmetro ao Navigate método que faz referência à Text propriedade da caixa de name 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()));
}

Em Page2.xaml, substitua o HyperlinkButton que você adicionou anteriormente pelo seguinte StackPanel. Isso adiciona um TextBlock para exibir a cadeia de caracteres de texto passada de MainPage.

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

Page2 No arquivo code-behind, adicione o seguinte código para substituir o 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);
}

Execute o aplicativo, digite seu nome na caixa de texto e clique no link que diz Click to go to page 2.

Quando o Click evento do HyperlinkButton em MainPage chama Frame.Navigate(typeof(Page2), name.Text), a name.Text propriedade é passada para Page2e o valor dos dados do evento é usado para a mensagem exibida na página.

5. Armazenar uma página em cache

O estado e o conteúdo da página não são armazenados em cache por padrão. Portanto, se quiser informações de cache, habilite-o em cada página do seu aplicativo.

Em nosso exemplo básico ponto a ponto, quando você clica no Click to go to page 1 link em Page2, o TextBox (e qualquer outro campo) em MainPage é definido como seu estado padrão. Uma maneira de contornar isso é usar a propriedade NavigationCacheMode para especificar que uma página foi adicionada ao cache de página do quadro.

Por padrão, uma nova instância de página é criada com seus valores padrão sempre que ocorre a navegação. Em MainPage.xaml, defina EnabledNavigationCacheMode como (na marca de aberturaPage) para armazenar em cache a página e manter todos os valores de conteúdo e estado da página até que o cache de página do quadro seja excedido. Defina NavigationCacheMode como Required se quiser ignorar os limites de CacheSize, que especificam o número de páginas no histórico de navegação que podem ser armazenadas em cache para o quadro. No entanto, lembre-se que os limites de tamanho de cache podem ser cruciais, dependendo dos limites de memória de um dispositivo.

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

Agora, quando você clica novamente em main página, o nome inserido na caixa de texto ainda está lá.

6. Personalizar animações de transição de página

Por padrão, cada página é animada no quadro quando ocorre a navegação. A animação padrão é uma animação de "entrada" que faz com que a página deslize para cima da parte inferior da janela. No entanto, você pode escolher diferentes opções de animação que melhor se adaptem à navegação do seu aplicativo. Por exemplo, você pode usar uma animação de "drill-in" para dar a sensação de que o usuário está se aprofundando em seu aplicativo ou uma animação de slide horizontal para dar a sensação de que duas páginas são pares. Para obter mais informações, consulte Transições de página.

Essas animações são representadas por subclasses de NavigationTransitionInfo. Para especificar a animação a ser usada para uma transição de página, você usará a terceira sobrecarga do Navigate método e passará uma NavigationTransitionInfo subclasse como o terceiro parâmetro (infoOverride). Esta é a assinatura dessa Navigate sobrecarga:

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

HyperlinkButton_Click No manipulador de eventos do MainPage arquivo code-behind, adicione um terceiro parâmetro ao Navigate método que define o infoOverride parâmetro como um SlideNavigationTransitionInfo com sua propriedade Effect definida como 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);
}

HyperlinkButton_Click No manipulador de eventos do Page2 arquivo code-behind, defina o infoOverride parâmetro como um SlideNavigationTransitionInfo com sua propriedade Effect definida como 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);
}

Agora, quando você navega entre páginas, as páginas deslizam para a esquerda e para a direita, o que fornece uma sensação mais natural para essa transição e reforça a conexão entre as páginas.