Поделиться через


Реализация навигации между двумя страницами

Узнайте, как использовать кадр и страницы, чтобы включить базовую одноранговую навигацию в приложении.

одноранговая навигация

Почти для каждого приложения требуется навигация между страницами. Даже простое приложение с одной страницей содержимого обычно имеет страницу параметров, требующую навигации. В этой статье мы рассмотрим основы добавления XAML Page в приложение и использования Frame навигации между страницами.

Внимание

Для этого примера мы используем шаблон пустого приложения из Microsoft Visual Studio. Существуют различия в шаблонах для приложений пакета SDK для приложений Windows или WinUI 3 и приложений UWP, поэтому не забудьте выбрать правильную вкладку для типа приложения.

1. Создание пустого приложения

Чтобы создать пустое приложение в Visual Studio, выполните следующее:

  1. Чтобы настроить среду разработки на компьютере, выполните инструкции из статьи Установка средств для пакета SDK для приложений Windows.
  2. В окне запуска Microsoft Visual Studio выберите "Создать проект" или в меню Visual Studio выберите "Создать>проект".>
  3. В раскрывающихся списках диалогового окна "Создание проекта" выберите C# или C++, Windows и WinUI соответственно.
  4. Выберите шаблон проекта Blank App, Packaged (WinUI 3 in Desktop) (Пустое, упакованное приложение (WinUI 3 в классических приложениях)) и щелкните Далее. Этот шаблон создает классическое приложение с пользовательским интерфейсом на основе WinUI 3.
  5. В поле "Имя проекта" введите BasicNavigationи нажмите кнопку "Создать".
  6. Чтобы запустить программу, выберите "Начать отладку>" в меню или нажмите клавишу F5. Выполните сборку и запустите решение на компьютере для разработки, чтобы убедиться, что приложение выполняется без ошибок. Отображается пустая страница.
  7. Чтобы остановить отладку и вернуться в Visual Studio, выйдите из приложения или нажмите кнопку Остановить отладку в меню.
  8. Удалите любой пример кода, который включен в шаблон из 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. Добавление базовых страниц

Шаблон пустого приложения не создает для вас несколько страниц приложений. Прежде чем переходить между страницами, необходимо добавить некоторые страницы в приложение.

Чтобы добавить новый элемент в приложение, выполните приведенные далее действия.

  1. В Обозреватель решений щелкните правой кнопкой мыши BasicNavigation узел проекта, чтобы открыть контекстное меню.
  2. Выберите "Добавить>новый элемент" в контекстном меню.
  3. В диалоговом окне "Добавить новый элемент" выберите узел WinUI в левой области, а затем в средней области выберите пустую страницу (WinUI 3).
  4. В поле "Имя" введите MainPage и нажмите кнопку "Добавить".
  5. Повторите шаги 1-4, чтобы добавить вторую страницу, но в поле "Имя " введите Page2.

Теперь эти файлы должны быть перечислены в рамках проекта BasicNavigation .

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

Внимание

Для проектов 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 добавляется следующее:

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.xamlHyperlinkButton добавленную ранее версию следующим элементом 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.xamlHyperlinkButton добавленную ранее версию следующим 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 ссылки Page2TextBox (и в любом другом поле) 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);
}

Теперь, когда вы переходите между страницами, страницы слайд влево и вправо, что обеспечивает более естественное ощущение этого перехода и усиливает связь между страницами.