Реализация навигации между двумя страницами
Узнайте, как использовать кадр и страницы, чтобы включить базовую одноранговую навигацию в приложении.
Почти каждое приложение требует навигации между страницами. Даже простое приложение с одной страницей содержимого обычно имеет страницу параметров, требующую навигации. В этой статье мы рассмотрим основы добавления XAML Page
в приложение и использования Frame
для навигации между страницами.
Важно!
В этом примере используется шаблон Пустое приложение из Microsoft Visual Studio. Существуют различия в шаблонах для приложений Windows App SDK/WinUI 3 и приложений UWP, поэтому не забудьте выбрать правильную вкладку для своего типа приложения.
- Область применения: Windows App SDK/WinUI3
- Важные API: класс Microsoft.UI.Xaml.Controls.Frame, класс Microsoft.UI.Xaml.Controls.Page, пространство имен Microsoft.UI.Xaml.Navigation
1. Создайте пустое приложение
Чтобы создать пустое приложение в Visual Studio, выполните следующие действия.
- Чтобы настроить среду разработки на компьютере, выполните инструкции из статьи Установка средств для пакета SDK для приложений Windows.
- В начальном окне Microsoft Visual Studio выберите Создать проект или в меню Visual Studio выберите Файл>Новый>проект.
- В раскрывающихся списках диалогового окна Создание проекта выберите C# или C++, Windows и WinUI соответственно.
- Выберите шаблон проекта Blank App, Packaged (WinUI 3 in Desktop) (Пустое, упакованное приложение (WinUI 3 в классических приложениях)) и щелкните Далее. Этот шаблон создает классическое приложение с пользовательским интерфейсом на основе WinUI 3.
- В поле Имя проекта введите
BasicNavigation
и нажмите кнопку Создать. - Чтобы запустить программу, выберите Отладка>Начать отладку в меню или нажмите клавишу F5. Выполните сборку и запустите решение на компьютере для разработки, чтобы убедиться, что приложение выполняется без ошибок. Отобразится пустая страница.
- Чтобы остановить отладку и вернуться в Visual Studio, выйдите из приложения или нажмите кнопку Остановить отладку в меню.
- Удалите все примеры кода, включенные в шаблон, из
MainWindow.xaml
файлов кода программной части иMainWindow
.
Совет
Дополнительные сведения см. в статье Создание первого проекта WinUI 3 (Windows App SDK).
2. Переход между страницами с помощью фрейма
Если приложение содержит несколько страниц, вы используете frame для перехода между ними. Класс Frame
поддерживает различные методы навигации, такие как Navigate, GoBack и GoForward, а также свойства BackStack, ForwardStack и BackStackDepth.
При создании нового проекта Windows App SDK в Visual Studio шаблон проекта создает MainWindow
класс (типа Microsoft.UI.Xaml.Window). Однако он не создает фрейм или страницу и не предоставляет код навигации.
Чтобы включить навигацию между страницами, добавьте в Frame
качестве корневого MainWindow
элемента . Это можно сделать в переопределении метода Application.OnLaunched в файле кода программной App.xaml
части. App
Откройте файл кода программной части, обновите OnLaunched
переопределение и обработайте событие NavigationFailed, как показано ниже.
// 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);
}
Примечание
Для приложений с более сложной навигацией обычно используется NavigationView в качестве корневого элемента MainWindow и в Frame
качестве содержимого представления навигации. Дополнительные сведения см. в разделе Представление навигации.
Метод Navigate используется для отображения содержимого в этом объекте Frame
. MainPage.xaml
Здесь передается Navigate
в метод , поэтому метод загружается MainPage
Frame
в .
Если переход к начальному окну приложения завершается сбоем NavigationFailed
, возникает событие, и этот код создает исключение в обработчике событий.
3. Добавление базовых страниц
Шаблон "Пустое приложение " не создает несколько страниц приложений. Прежде чем переходить между страницами, необходимо добавить несколько страниц в приложение.
Чтобы добавить новый элемент в приложение, выполните указанные далее действия.
- В Обозреватель решений щелкните правой
BasicNavigation
кнопкой мыши узел проекта, чтобы открыть контекстное меню. - Выберите Добавить>новый элемент в контекстном меню.
- В диалоговом окне Добавление нового элемента выберите узел WinUI на левой панели, а затем выберите Пустая страница (WinUI 3) в средней области.
- В поле Имя введите
MainPage
и нажмите кнопку Добавить . - Повторите шаги 1–4, чтобы добавить вторую страницу, но в поле Имя введите
Page2
.
Теперь эти файлы должны быть перечислены как часть проекта BasicNavigation
.
C# | C++ |
---|---|
|
|
Важно!
Для проектов C++ необходимо добавить директиву #include
в файл заголовка каждой страницы, которая ссылается на другую страницу. В приведенном здесь примере межстраничной навигации файл mainpage.xaml.h содержит #include "Page2.xaml.h"
, в свою очередь, page2.xaml.h содержит #include "MainPage.xaml.h"
.
Шаблоны страниц C++ также содержат пример Button
и код обработчика щелчков, который необходимо удалить из файлов XAML и программной части для страницы.
Добавление содержимого на страницы
В MainPage.xaml
замените существующее содержимое страницы следующим содержимым:
<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>
Этот КОД XAML добавляет:
- Элемент TextBlock с именем
pageTitle
со свойством Text , свойствуMain Page
Text, присвоено значение в качестве дочернего элемента корневого элемента Grid. - Элемент HyperlinkButton , используемый для перехода на следующую страницу в качестве дочернего элемента корневого элемента Grid.
MainPage
В файле кода программной части добавьте следующий код для обработки Click
события HyperlinkButton, добавленного для включения навигации по 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
является подклассом класса Page. Класс Page
имеет доступное только для чтения свойство Frame , которое получает Frame
объект , содержащий Page
. Click
Когда обработчик HyperlinkButton
событий в MainPage
вызывает Frame.Navigate(typeof(Page2))
, Frame
отображает содержимое Page2.xaml
.
Всякий раз, когда страница загружается в кадр, эта страница добавляется как PageStackEntry в BackStack или ForwardStackкадра, что позволяет вести журнал и переход в обратном направлении.
Теперь сделайте то же самое в Page2.xaml
. Замените существующее содержимое страницы следующим содержимым:
<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
В файле кода программной части добавьте следующий код для обработки Click
события HyperlinkButton для перехода к 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>());
}
Выполните сборку и запуск приложения. Щелкните ссылку «Click to go to page 2» (Нажмите, чтобы перейти к странице 2). Вторая страница с надписью «Page 2» (Страница 2) в верхней части загрузится и появится в фрейме. Теперь щелкните ссылку на странице 2, чтобы вернуться на главную страницу.
4. Передача информации между страницами
Теперь приложение перемещается между двумя страницами, но пока не делает ничего интересного. Часто, если в приложении есть несколько страниц, необходим общий доступ к информации. Теперь вы передайте некоторые сведения с первой страницы на вторую.
В MainPage.xaml
замените HyperlinkButton
добавленный ранее элемент на следующий StackPanel. При этом добавляется метка TextBlock и TextBoxname
для ввода текстовой строки.
<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>
Теперь вы используете вторую перегрузку Navigate
метода и передайте текст из текстового поля в качестве второго параметра. Вот сигнатура этой Navigate
перегрузки:
public bool Navigate(System.Type sourcePageType, object parameter);
bool Navigate(TypeName const& sourcePageType, IInspectable const& parameter);
В обработчике HyperlinkButton_Click
событий файла кода программной MainPage
части добавьте второй параметр в Navigate
метод, который ссылается на Text
свойство текстового name
поля.
// 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()));
}
В Page2.xaml
замените добавленный HyperlinkButton
ранее на следующий StackPanel
. При этом будет добавлен элемент TextBlock для отображения текстовой строки, передаваемой из 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
В файле кода программной части добавьте следующий код, чтобы переопределить 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);
}
Запустите приложение, введите свое имя в текстовое поле и щелкните ссылку с надписью Click to go to page 2
.
Click
Когда событие HyperlinkButton
in вызывает Frame.Navigate(typeof(Page2), name.Text)
, name.Text
свойство передается Page2
в MainPage
, а значение из данных события используется для сообщения, отображаемого на странице.
5. Кэширование страницы
Содержимое и состояние страницы не кэшируются по умолчанию, поэтому если требуется кэшировать информацию, кэширование нужно включать для каждой страницы приложения.
В нашем базовом одноранговом примере при щелчке Click to go to page 1
по ссылке TextBox
в Page2
параметре (и любом другом поле) в MainPage
устанавливается состояние по умолчанию. Один способов обойти эту проблему — использовать свойство NavigationCacheMode, чтобы указать, что страница будет добавлена в кэш страницы фрейма.
По умолчанию при каждом переходе создается новый экземпляр страницы со значениями по умолчанию. В MainPage.xaml
задайте значение NavigationCacheMode
Enabled
(в открывающем Page
теге), чтобы кэшировать страницу и сохранять все значения содержимого и состояния страницы до тех пор, пока не будет превышен кэш страницы для кадра. Задайте параметру NavigationCacheMode значение Required, если требуется игнорировать ограничения CacheSize, обозначающие число страниц в журнале навигации, которые можно кэшировать для кадра. Однако следует помнить, что ограничения размера кэша могут быть критическими в зависимости от ограничений памяти устройства.
<Page
x:Class="BasicNavigation.MainPage"
...
mc:Ignorable="d"
NavigationCacheMode="Enabled">
Теперь, когда вы щелкаете main страницу, имя, которое вы ввели в текстовом поле, по-прежнему будет там.
6. Настройка анимации перехода страницы
По умолчанию каждая страница анимируется в кадр при переходе. Анимация по умолчанию — это анимация входа, которая приводит к тому, что страница будет скользить вверх от нижней части окна. Однако вы можете выбрать различные параметры анимации, которые лучше подходят для навигации вашего приложения. Например, можно использовать анимацию детализации, чтобы создать ощущение, что пользователь углубляется в приложение, или горизонтальную анимацию слайдов, чтобы создать ощущение, что две страницы являются одноранговым элементом. Дополнительные сведения см. в разделе Переходы страниц.
Эти анимации представлены подклассами NavigationTransitionInfo. Чтобы указать анимацию для перехода страницы, используйте третью перегрузку Navigate
метода и передайте NavigationTransitionInfo
подкласс в качестве третьего параметра (infoOverride
). Вот сигнатура этой Navigate
перегрузки:
public bool Navigate(System.Type sourcePageType,
object parameter,
NavigationTransitionInfo infoOverride);
bool Navigate(TypeName const& sourcePageType,
IInspectable const& parameter,
NavigationTransitionInfo const& infoOverride);
В обработчике HyperlinkButton_Click
событий файла кода программной MainPage
части добавьте третий параметр в Navigate
метод , который задает infoOverride
параметру Значение SlideNavigationTransitionInfo , а свойству Effect присвоено значение 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
событий файла кода программной Page2
части задайте infoOverride
параметру Значение SlideNavigationTransitionInfo , а свойству Effect присвоено значение 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);
}
Теперь при переходе между страницами страницы перемещаются влево и вправо, что обеспечивает более естественное ощущение этого перехода и усиливает связь между страницами.
Похожие статьи
Windows developer
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по