Бөлісу құралы:


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

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

Значок коллекции WinUI 3 Приложение WinUI 3 Gallery содержит интерактивные примеры элементов управления и функций WinUI. Получите приложение из Microsoft Store или просмотрите исходный код GitHub.

Подсказка

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

Обзор API

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

XAML Window и AppWindow

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

Более подробное описание Window и AppWindow см. в разделе обзора "Оконная система в WinUI и Windows App SDK".

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. В области Solution Explorer щелкните правой кнопкой мыши имя проекта и выберите Add > New Item...
  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. Используйте метод WindowActivate для отображения нового окна.

    newWindow.Activate();
    

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

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

В этом случае уникальный идентификатор WindowId следует использовать для отслеживания экземпляров окна в объекте Dictionary, используя WindowId как Key, а экземпляр Window как Value. (TabView tab tear-out API также используют 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.Closed, чтобы удалить его из 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 страницы, а не в конструкторе, чтобы XamlRootnull не был.

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];
        }
    }
}