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


Отображение нескольких представлений для приложения

Макет, показывающий приложение с несколькими окнами

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

Важные API: пространство имен Windows.UI.ViewManagement, пространство имен Windows.UI.WindowManagement

Когда приложение должно использовать несколько представлений?

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

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

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

Чтобы создать отдельные экземпляры приложения (а не отдельные окна одного экземпляра), обратитесь к статье Создание приложения Windows с несколькими экземплярами.

Окна содержимого

Существует несколько способов размещения содержимого Windows внутри приложения.

  • CoreWindow/ApplicationView

    Представление приложения — это связывание потока и окна, которое приложение использует для отображения содержимого. Первое представление, созданное при запуске приложения, называется основным представлением. Каждый объект CoreWindow и ApplicationView работает в своем собственном потоке. Работа с различными потоками пользовательского интерфейса может усложнить многооконные приложения.

    Основное представление приложения всегда размещается в ApplicationView. Содержимое в дополнительном окне может размещаться в ApplicationView или AppWindow.

    Узнайте, как использовать ApplicationView для отображения дополнительных окон в приложении, ознакомившись с разделом Использование ApplicationView.

  • AppWindow

    AppWindow упрощает создание приложений Windows с несколькими окнами, так как оно работает в одном потоке пользовательского интерфейса, созданном из него.

    Класс AppWindow и другие интерфейсы API в пространстве имен WindowManagement доступны, начиная с Windows 10 версии 1903 (пакет SDK 18362). Если приложение нацелено на более ранние версии Windows 10, для создания дополнительных окон необходимо использовать ApplicationView.

    Узнайте, как использовать AppWindow для отображения дополнительных окон в приложении, ознакомившись с разделом Использование AppWindow.

    Примечание.

    AppWindow сейчас находится на этапе предварительной версии. Это означает, что вы можете отправлять приложения, использующие AppWindow, в Store, но некоторые компоненты платформ не работают с AppWindow (см. раздел Ограничения).

  • DesktopWindowXamlSource (области XAML)

    Содержимое UWP XAML в приложении Win32 (использующем HWND), также известное как области XAML, размещается в DesktopWindowXamlSource.

    Чтобы узнать больше об областях XAML, ознакомьтесь с использованием API размещения UWP XAML в классическом приложении.

Создание кода, переносимого между окнами содержимого

Когда содержимое XAML отображается в CoreWindow, всегда существуют связанные с ним экземпляры ApplicationView и Window XAML. Интерфейсы API для этих классов можно использовать для получения таких сведений, как границы окна. Для получения экземпляра этих классов используется статический метод CoreWindow.GetForCurrentThread, метод ApplicationView.GetForCurrentView или свойство Window.Current. Кроме того, существует множество классов, использующих шаблон GetForCurrentView для получения экземпляра класса, например DisplayInformation.GetForCurrentView.

Эти API работают, так как существует только одно дерево содержимого XAML для CoreWindow/ApplicationView, поэтому XAML знает контекст, в котором размещена версия CoreWindow/ApplicationView.

Когда содержимое XAML выполняется в AppWindow или DesktopWindowXamlSource, можно одновременно выполнять несколько деревьев содержимого XAML в одном и том же потоке. В этом случае эти API не дают нужных сведений, так как содержимое больше не выполняется внутри текущего CoreWindow/ApplicationView (и окна XAML).

Чтобы обеспечить правильную работу кода во всех окнах содержимого, необходимо заменить интерфейсы API, использующие CoreWindow, ApplicationView и Window, новыми API, которые получают контекст из класса XamlRoot. Класс XamlRoot представляет дерево содержимого XAML и сведения о контексте, в котором он размещен, будь то CoreWindow, AppWindow или DesktopWindowXamlSource. Этот уровень абстракции позволяет писать единый код, не зависящий от того, в каком окне содержимого выполняется XAML.

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

Если вы использовали… Замените на…
CoreWindow.GetForCurrentThread().Bounds uiElement.XamlRoot.Size
CoreWindow.GetForCurrentThread().SizeChanged uiElement.XamlRoot.Changed
CoreWindow.Visible uiElement.XamlRoot.IsHostVisible
CoreWindow.VisibilityChanged uiElement.XamlRoot.Changed
CoreWindow.GetForCurrentThread().GetKeyState Без изменений. Это поддерживается в AppWindow и DesktopWindowXamlSource.
CoreWindow.GetForCurrentThread().GetAsyncKeyState Без изменений. Это поддерживается в AppWindow и DesktopWindowXamlSource.
Window.Current Возвращает основной объект Window XAML, который жестко привязан к текущему экземпляру CoreWindow. См. примечание после таблицы.
Window.Current.Bounds uiElement.XamlRoot.Size
Window.Current.Content UIElement root = uiElement.XamlRoot.Content
Window.Current.Compositor Без изменений. Это поддерживается в AppWindow и DesktopWindowXamlSource.
VisualTreeHelper.FindElementsInHostCoordinates
Хотя параметр UIElement является необязательным, метод вызывает исключение, если UIElement не предоставляется при размещении в области.
Определите элемент uiElement.XamlRoot как UIElement (не оставляйте его пустым).
VisualTreeHelper.GetOpenPopups
В приложениях с областями XAML это приведет к ошибке. В приложениях AppWindow это приведет к появлению всплывающих окон в главном окне.
VisualTreeHelper.GetOpenPopupsForXamlRoot(uiElement.XamlRoot)
FocusManager.GetFocusedElement FocusManager.GetFocusedElement(uiElement.XamlRoot)
contentDialog.ShowAsync() contentDialog.XamlRoot = uiElement.XamlRoot;
contentDialog.ShowAsync();
menuFlyout.ShowAt(null, new Point(10, 10)); menuFlyout.XamlRoot = uiElement.XamlRoot;
menuFlyout.ShowAt(null, new Point(10, 10));

Примечание.

Для содержимого XAML в DesktopWindowXamlSource в потоке существует экземпляр CoreWindow или Window, но он всегда невидимый и имеет размер 1x1. Он по-прежнему доступен для приложения, но не возвращает значимые границы или видимость.

Для содержимого XAML в AppWindow всегда будет существовать только один экземпляр CoreWindow в одном потоке. При вызове API GetForCurrentView или GetForCurrentThread возвращается объект, отражающий состояние CoreWindow в потоке, а не экземпляров AppWindow, которые могут выполняться в том же потоке.

Что рекомендуется и что не рекомендуется делать

  • Укажите явную точку входа в дополнительное представление, используя глиф "Открыть новое окно".
  • Обсудите предназначение дополнительного представления для пользователей.
  • Убедитесь, что приложение является полностью функциональным в отдельном представлении и пользователи будут открывать дополнительное представление только для удобства.
  • Не используйте дополнительное представление для уведомлений и других временных визуальных элементов.