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


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

В приложении WinUI 3 вы можете отобразить содержимое приложения в дополнительных окнах, работая над тем же потоком пользовательского интерфейса в каждом окне.

Приложение Галерея WinUI 3 включает интерактивные примеры большинства элементов управления, особенностей и возможностей WinUI 3. Получение приложения из Microsoft Store или получение исходного кода на GitHub

Подсказка

Распространенная причина использования нескольких окон заключается в том, чтобы вкладки TabView были вырваны в новое окно. Сведения и примеры, относящиеся к этому сценарию, см. в статье "Представлениетабуляции ".

Обзор API

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

XAML Window и AppWindow

Классы Window и AppWindow можно использовать для отображения части приложения в дополнительном окне. Важной особенностью окон WinUI является то, что каждый экземпляр использует один и тот же поток обработки пользовательского интерфейса (включая диспетчер событий), из которого они были созданы, что упрощает многоэкционные приложения.

Дополнительные сведения Windowсм. в AppWindow.

AppWindowPresenter

API AppWindowPresenter позволяет легко переключать окна в предварительно определенные конфигурации, например FullScreen или CompactOverlay. Дополнительные сведения см. в разделе Управление окнами приложений.

XamlRoot

Класс XamlRoot содержит дерево элементов XAML, подключает его к объекту узла окна и предоставляет такие сведения, как размер и видимость. Объект XamlRoot не создается напрямую. Вместо этого он создается при присоединении элемента XAML к элементу Window. Затем можно использовать свойство UIElement.XamlRoot для получения XamlRoot.

WindowId

WindowId — уникальный идентификатор окна приложения. Он создается автоматически и определяет как AppWindow, так и связанный с ним верхнеуровневый HWND в Win32.

Из визуального элемента можно получить доступ к UIElement.XamlRoot; затем XamlRoot.ContentIslandEnvironment; затем свойство ContentIslandEnvironment.AppWindowId содержит идентификатор окна, в котором находится UIElement.

Отображение нового окна

Вы можете создать новый Window в XAML или с помощью кода. При создании Window в XAML фактически создается подкласс Window класса. Например, ознакомьтесь с MainWindow.xaml, который создается шаблоном приложения Visual Studio.

Давайте рассмотрим шаги для отображения содержимого в новом окне.

Создание нового окна с помощью XAML

  1. В области обозревателя решений щелкните правой кнопкой мыши имя проекта и выберите "Добавить > новый элемент".
  2. В диалоговом окне "Добавление нового элемента" выберите WinUI в списке шаблонов в левой части окна.
  3. Выберите пустой Window шаблон.
  4. Присвойте файлу имя.
  5. Нажмите кнопку "Добавить".

Чтобы показать новое окно

  1. Создайте новый экземпляр Window, или Window подкласса, если вы создали Window подкласс с файлом .xaml.

    Window newWindow = new Window();
    
  2. Создайте содержимое окна.

    Если вы создали подкласс с файломWindow, можно добавить содержимое .xaml окна непосредственно в XAML. В противном случае вы добавите содержимое в код, как показано здесь.

    Обычно создается XAML Frame, а затем выполните переход Frame к XAML [Page](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.page, в котором вы определили содержимое вашего приложения. Дополнительные сведения о кадрах и страницах см. в разделе одноранговой навигации между двумя страницами.

    Frame contentFrame = new Frame();
    contentFrame.Navigate(typeof(SecondaryPage));
    

    Однако в AppWindow можно отобразить любое содержимое XAML, а не только Frame и Page. Например, можно отобразить только один элемент управления, например ColorPicker, как показано ниже.

  3. Задайте содержимое XAML свойству Content объекта Window.

    newWindow.Content = contentFrame;
    
  4. WindowВызовите . Активация метода для отображения нового окна.

    newWindow.Activate();
    

Отслеживайте экземпляры Window

Возможно, вы захотите получить доступ к Window экземплярам из других частей вашего приложения, но после создания экземпляра Window нет способа доступа к нему из другого кода, если не сохранить ссылку на него. Например, может потребоваться обработать Window. Событие SizeChanged для MainPage переупорядочения элементов пользовательского интерфейса при изменении размера окна или может быть кнопка "закрыть все", которая закрывает все отслеживаемые экземпляры Window.

В этом случае уникальный идентификатор WindowId следует использовать для отслеживания экземпляров окна в объекте Dictionary, используя WindowId как Key, а экземпляр Window как Value. (API-интерфейсы с разрывом вкладки TabView также используются WindowId для отслеживания Windows.)

Создайте в вашем App классе Dictionary в качестве статического свойства. Затем добавляйте каждую страницу в Dictionary, когда создаете ее, и удаляйте страницу при ее закрытии.

// App.xaml.cs
public partial class App : Application
{
    private Window? _window;
    public static Dictionary<WindowId, Window> ActiveWindows { get; set; } = new Dictionary<WindowId, Window>();

    // ...

    protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
    {
        _window = new MainWindow();
        _window.Activate();
        // Track the new window in the dictionary.
        ActiveWindows.Add(_window.AppWindow.Id, _window);
    }
}

Следующий код создает новое окно при нажатии кнопки MainPage. Метод TrackWindow добавляет новое окно в ActiveWindowsDictionaryи обрабатывает объектWindow . Закрытое событие, чтобы удалить его из ActiveWindows окна при закрытии окна.

// MainPage.xaml.cs
private Window CreateWindow()
{
    Window newWindow = new Window();

    // Configure the window.
    newWindow.AppWindow.Resize(new SizeInt32(1200, 800));
    newWindow.Title = "Window " + newWindow.AppWindow.Id.Value.ToString();
    newWindow.SystemBackdrop = new MicaBackdrop();

    TrackWindow(newWindow);
    return newWindow;
}

private void TrackWindow(Window window)
{
    window.Closed += (sender, args) => {
        App.ActiveWindows.Remove(window.AppWindow.Id, out window);
    };
    App.ActiveWindows.Add(window.AppWindow.Id, window);
}

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

Чтобы получить доступ к экземпляру Window из кода приложения, необходимо извлечь WindowId текущего окна, чтобы получить его из статического Dictionary в вашем классе App. Это следует сделать в обработчике событий loaded страницы, а не в конструкторе, чтобы XamlRoot не nullбыл.

public sealed partial class SecondaryPage : Page
{
    Window window;

    public SecondaryPage()
    {
        InitializeComponent();
        Loaded += AppWindowPage_Loaded;
    }

    private void AppWindowPage_Loaded(object sender, RoutedEventArgs e)
    {
        // Get the reference to this Window that was stored when it was created.
        // Do this in the Page Loaded handler rather than the constructor to
        // ensure that the XamlRoot is created and attached to the Window.
        WindowId windowId = this.XamlRoot.ContentIslandEnvironment.AppWindowId;

        if (App.ActiveWindows.ContainsKey(windowId))
        {
            window = App.ActiveWindows[windowId];
        }
    }
}