Реализация навигации между двумя страницами
Узнайте, как использовать кадр и страницы, чтобы включить базовую одноранговую навигацию в приложении.
Почти для каждого приложения требуется навигация между страницами. Даже простое приложение с одной страницей содержимого обычно имеет страницу параметров, требующую навигации. В этой статье мы рассмотрим основы добавления XAML Page
в приложение и использования Frame
навигации между страницами.
Внимание
Для этого примера мы используем шаблон пустого приложения из Microsoft Visual Studio. Существуют различия в шаблонах для приложений пакета SDK для приложений Windows или WinUI 3 и приложений UWP, поэтому не забудьте выбрать правильную вкладку для типа приложения.
- Область применения: пакет SDK для приложений Windows или 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 (пакет SDK для приложений Windows).
2. Использование кадра для перехода между страницами
При наличии нескольких страниц приложение использует кадр для перехода между ними. Класс Frame
поддерживает различные методы навигации, такие как Navigate, GoBack и GoForward, а также свойства, такие как BackStack, ForwardStack и BackStackDepth.
При создании проекта пакета SDK для приложений Windows в 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
в файл заголовка каждой страницы, которая ссылается на другую страницу. Пример навигации между страницами #include "Page2.xaml.h"
, представленный здесь, содержит файл mainpage.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 с его свойством Text, заданным
Main Page
как дочерний элемент корневой сетки.pageTitle
- Элемент ГиперссылкаButton , используемый для перехода к следующей странице в качестве дочернего элемента корневой сетки.
MainPage
В файле программной части добавьте следующий код для обработки Click
события гиперссылкиButton, добавленного для включения навигации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
. Когда обработчик HyperlinkButton
событий вызовов Frame.Navigate(typeof(Page2))
MainPage
отображает Frame
содержимое Page2.xaml
.Click
Каждый раз, когда страница загружается в кадр, эта страница добавляется в качестве страницы 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
события гиперссылкиButton для перехода 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>());
}
Выполните сборку и запустите приложение. Щелкните ссылку, которая говорит "Щелкните, чтобы перейти на страницу 2". Вторая страница, которая говорит "Страница 2" в верхней части экрана, должна быть загружена и отображена в кадре. Теперь щелкните ссылку на странице 2, чтобы вернуться на главную страницу.
4. Передача данных между страницами
Теперь приложение перемещается между двумя страницами, но это действительно не делает ничего интересного еще. Часто, когда приложение имеет несколько страниц, страницы должны предоставлять общий доступ к информации. Теперь вы передайте некоторые сведения с первой страницы на вторую страницу.
Замените MainPage.xaml
HyperlinkButton
добавленную ранее версию следующим элементом StackPanel. При этом добавляется метка TextBlock и текстовое поле name
для ввода текстовой строки.
<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
вызова name.Text
MainPage
Frame.Navigate(typeof(Page2), name.Text)
передается Page2
свойству, а значение из данных события используется для сообщения, отображаемого на странице.
5. Кэширование страницы
Содержимое и состояние страницы не кэшируются по умолчанию, поэтому если требуется кэшировать информацию, кэширование нужно включать для каждой страницы приложения.
В нашем базовом примере однорангового узла при щелчке Click to go to page 1
ссылки Page2
TextBox
(и в любом другом поле) MainPage
задано его состояние по умолчанию. Один из способов обойти это — использовать свойство NavigationCacheMode , чтобы указать, что страница будет добавлена в кэш страницы кадра.
По умолчанию создается новый экземпляр страницы со значениями по умолчанию при каждом переходе. В MainPage.xaml
поле установите значение NavigationCacheMode
Enabled
(в открываемом Page
теге), чтобы кэшировать страницу и сохранить все значения содержимого и состояния страницы до тех пор, пока кэш страницы не будет превышен. Задайте параметру NavigationCacheMode значение Required, если требуется игнорировать ограничения CacheSize, обозначающие число страниц в журнале навигации, которые можно кэшировать для кадра. Однако следует помнить, что ограничения размера кэша могут быть критическими в зависимости от ограничений памяти устройства.
<Page
x:Class="BasicNavigation.MainPage"
...
mc:Ignorable="d"
NavigationCacheMode="Enabled">
Теперь, когда вы щелкаете назад на главную страницу, имя, которое вы ввели в текстовом поле, все еще есть.
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