Отображение нескольких представлений с помощью ApplicationView

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

Важные API-интерфейсы: ApplicationViewSwitcher, CreateNewView

Что такое представление?

Представление приложения — это совокупность 1:1 потока и окна, которая используется приложением для отображения содержимого. Оно представляется объектом Windows.ApplicationModel.Core.CoreApplicationView.

Представления управляются объектом CoreApplication. Необходимо вызвать CoreApplication.CreateNewView, чтобы создать объект CoreApplicationView. CoreApplicationView объединяет CoreWindow и CoreDispatcher (которые хранятся в свойствах CoreWindow и Dispatcher). CoreApplicationView можно считать объектом, который использует среда выполнения Windows для взаимодействия с основной системой Windows.

Обычно работать непосредственно с CoreApplicationView не нужно. Вместо этого среда выполнения Windows предоставляет класс ApplicationView в пространстве имен Windows.UI.ViewManagement. Этот класс предоставляет свойства, методы и события, которые используются при взаимодействии приложения с системой работы с окнами. Для работы с ApplicationView вызовите статический метод ApplicationView.GetForCurrentView, который получает экземпляр ApplicationView, связанный с текущим потоком CoreApplicationView.

Аналогично, платформа XAML создает программу-оболочку для объекта CoreWindow в объекте Windows.UI.XAML.Window. В приложении XAML обычно происходит взаимодействие с объектом Window вместо непосредственной работы с CoreWindow.

Отображение нового представления

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

Рассмотрим шаги для создания нового представления. В данном примере новое представление запускается в ответ на нажатие кнопки.

private async void Button_Click(object sender, RoutedEventArgs e)
{
    CoreApplicationView newView = CoreApplication.CreateNewView();
    int newViewId = 0;
    await newView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        Frame frame = new Frame();
        frame.Navigate(typeof(SecondaryPage), null);   
        Window.Current.Content = frame;
        // You have to activate the window in order to show it later.
        Window.Current.Activate();

        newViewId = ApplicationView.GetForCurrentView().Id;
    });
    bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewId);
}

Отображение нового представления

  1. Вызовите CoreApplication.CreateNewView, чтобы создать новое окно и поток для содержимого представления.

    CoreApplicationView newView = CoreApplication.CreateNewView();
    
  2. Отслеживайте Id нового представления. Это понадобится для отображения представления позже.

    Можно создать некоторую инфраструктуру в приложении, чтобы упростить отслеживание представлений, которые вы создаете. Пример: класс ViewLifetimeControl в разделе Пример MultipleViews.

    int newViewId = 0;
    
  3. В новом потоке заполните окно.

    При помощи метода CoreDispatcher.RunAsync запланируйте задачу в потоке пользовательского интерфейса для нового представления. Используйте лямбда-выражение, чтобы передать функцию методу RunAsync как аргумент. Результаты работы лямбда-функции влияют на поток нового представления.

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

    После заполнения нового Window необходимо вызвать метод Activate Window для отображения Window позднее. Результаты влияют на поток нового представления, так что активируется новое Window.

    Наконец, скачайте Id нового используемого представления для его отображения позже. Результаты также влияют на поток нового представления, поэтому ApplicationView.GetForCurrentView получает Id нового представления.

    await newView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        Frame frame = new Frame();
        frame.Navigate(typeof(SecondaryPage), null);   
        Window.Current.Content = frame;
        // You have to activate the window in order to show it later.
        Window.Current.Activate();
    
        newViewId = ApplicationView.GetForCurrentView().Id;
    });
    
  4. Отобразите новое представление, вызвав ApplicationViewSwitcher.TryShowAsStandaloneAsync.

    После создания нового представления, вы сможете отобразить его в новом окне с помощью метода ApplicationViewSwitcher.TryShowAsStandaloneAsync. Параметр viewId в этом методе представляет собой целое число, уникальным образом идентифицирующее каждое представление в приложении. Вы получите представление Id, воспользовавшись свойством ApplicationView.Id или методом ApplicationView.GetApplicationViewIdForWindow.

    bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewId);
    

Главное представление

Первое представление, создаваемое при запуске приложения, называется главным. Это представление хранится в свойстве CoreApplication.MainView, и его свойство IsMain имеет значение true. Вам не нужно создавать это представление, его создает приложение. Поток главного представления служит диспетчером для приложения, и события активации в приложении происходят в этом потоке.

Если открыты вспомогательные представления, окно главного представления может быть скрыто, например, по нажатию кнопки закрытия (x) на панели заголовка окна, но его поток остается активным. Вызов Close в Window главного представления приведет к возникновению InvalidOperationException. (Чтобы закрыть приложение, используйте Application.Exit.) Если работа потока главного представления завершается, приложение закрывается.

Дополнительные представления

Другие представления, в том числе все представления, создаваемые по вызову CreateNewView в коде приложения, являются дополнительными представлениями. Как главное представление, так и дополнительные представления хранятся в коллекции CoreApplication.Views. Обычно дополнительные представления создаются в ответ на действия пользователя. В некоторых случаях система создает дополнительные представления для приложения.

Примечание

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

Переключение между представлениями

Следует учесть необходимость предоставления пользователю возможности вернуться в главное окно из дополнительного. Для этого используйте метод ApplicationViewSwitcher.SwitchAsync. Вызовите этот метод из потока окна, из которого вы переключаетесь, и передайте идентификатор представления окна, на которое вы переключаетесь.

await ApplicationViewSwitcher.SwitchAsync(viewIdToShow);

Используя SwitchAsync, можно определить, следует ли закрыть начальное окно и удалить его из панели задач, указав значение ApplicationViewSwitchingOptions.