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 as páginas. 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, abordamos as noções básicas sobre como adicionar um XAML Page ao seu aplicativo e usar um Frame para navegar entre as 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, certifique-se de selecionar 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 Visual Studio, escolha Arquivar>Novo>Projeto.
  3. Nos filtros suspensos da caixa de diálogo 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 code-behind.

Dica

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

2. Use um quadro para navegar entre as páginas

Quando seu aplicativo tem várias páginas, você usa 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 do 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, de modo que o método seja carregado MainPage 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. Adicione páginas básicas

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

Para adicionar um novo item ao seu aplicativo:

  1. No 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 do meio.
  4. Na caixa Nome, digite 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, digite 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
  • Página2.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>

Esse XAML adiciona:

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

// 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 arquivo Page. Quando o Click manipulador de HyperlinkButton eventos do in MainPage chama Frame.Navigate(typeof(Page2)), o exibe Frame 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 para trás.

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

Compilar e executar o aplicativo. Clique no link que diz "Clique para ir para a página 2". A segunda página que diz "Página 2" na parte superior deve ser carregada e exibida no quadro. Agora clique no link na página 2 para voltar à página principal.

4. Passe informações entre as páginas

Seu aplicativo agora navega entre duas páginas, mas ainda não faz nada de interessante. Muitas vezes, 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 seguinte StackPanel. Isso adiciona um rótulo TextBlock e um TextBox name 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. Aqui está 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 in HyperlinkButton MainPage chama Frame.Navigate(typeof(Page2), name.Text), a name.Text propriedade é passada para Page2, e o valor dos dados do evento é usado para a mensagem exibida na página.

5. Armazene 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 seja 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 NavigationCacheMode como Enabled (na tag de abertura Page ) para armazenar a página em cache e reter 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 em voltar para a página principal, o nome que você digitou na caixa de texto ainda está lá.

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

Por padrão, cada página é animada no quadro quando a navegação ocorre. A animação padrão é uma animação de "entrada" que faz com que a página deslize para cima a partir da parte inferior da janela. No entanto, você pode escolher diferentes opções de animação que melhor se adequam à navegação do seu aplicativo. Por exemplo, você pode usar uma animação de "detalhamento" 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 Navigate terceira sobrecarga do método e passará uma NavigationTransitionInfo subclasse como o terceiro parâmetro (infoOverride). Aqui está 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 as páginas, as páginas deslizam para a esquerda e para a direita, o que proporciona uma sensação mais natural para essa transição e reforça a conexão entre as páginas.