WinUI 3 アプリでは、各ウィンドウで同じ UI スレッドで作業しながら、セカンダリ ウィンドウにアプリのコンテンツを表示できます。
- 重要な API: Microsoft.UI.Windowing 名前空間、 Window クラス、 AppWindow クラス
WinUI 3 ギャラリー アプリには、ほとんどの WinUI 3 コントロールと機能の対話型の例が含まれています。 Microsoft Store からアプリを取得するか、GitHub でソース コードを取得する
ヒント
複数のウィンドウを使用する一般的な理由は、 TabView タブを新しいウィンドウに引き裂くことを許可するためです。 このシナリオに固有の情報と例については、タブ ビューの記事の「タブの破棄」を参照してください。
API の概要
複数のウィンドウでコンテンツを表示するために使用する重要な API の一部を次に示します。
XAML Window と AppWindow
WindowクラスとAppWindow クラスを使用して、セカンダリ ウィンドウにアプリの一部を表示できます。 WinUI ウィンドウの重要な機能は、各インスタンスが作成元の同じ UI 処理スレッド (イベント ディスパッチャーを含む) を共有することで、マルチウィンドウ アプリを簡略化することです。
とWindowの詳細については、AppWindowに関するページを参照してください。
AppWindowPresenter
AppWindowPresenter API を使用すると、ウィンドウをFullScreenやCompactOverlayなどの定義済みの構成に簡単に切り替えることができます。 詳細については、「アプリ ウィンドウ
XamlRoot
XamlRoot クラスは、XAML 要素ツリーを保持し、それをウィンドウ ホスト オブジェクトに接続し、サイズや可視性などの情報を提供します。 XamlRoot オブジェクトは直接作成しません。 代わりに、XAML 要素を Windowにアタッチするときに作成されます。 その後、 UIElement.XamlRoot プロパティを使用して XamlRoot を取得できます。
WindowId
WindowId は、アプリ ウィンドウの一意の識別子です。 これは自動的に作成され、関連付けられている AppWindow と最上位の Win32 HWND の両方を識別します。
ビジュアル要素から UIElement.XamlRoot にアクセスできます。次に XamlRoot.ContentIslandEnvironment;その後、 ContentIslandEnvironment.AppWindowId プロパティには、UIElement が存在するウィンドウの ID が含まれます。
新しいウィンドウを表示する
XAML またはコードで新しい Window を作成できます。 XAML で Window を作成する場合は、実際には Window クラスのサブクラスを作成します。 たとえば、Visual Studio アプリ テンプレートによって作成された MainWindow.xaml を参照してください。
新しいウィンドウにコンテンツを表示する手順を見てみましょう。
XAML で新しいウィンドウを作成するには
- ソリューション エクスプローラー ウィンドウで、プロジェクト名を右クリックし、[新しい項目>追加]を選択します。
- [ 新しい項目の追加] ダイアログで、ウィンドウの左側にあるテンプレートの一覧で WinUI を選択します。
- 空白のWindow テンプレートを選択します。
- ファイルに名前を付けます。
- [追加] を押します。
新しいウィンドウを表示するには
Windowの新しいインスタンスをインスタンス化するか、Window ファイルでWindowサブクラスを作成した場合は
.xamlサブクラスをインスタンス化します。Window newWindow = new Window();ウィンドウの内容を作成します。
Window ファイルを使用して
.xamlサブクラスを作成した場合は、XAML で直接ウィンドウ コンテンツを追加できます。 それ以外の場合は、次のようにコードにコンテンツを追加します。XAML Frameを作成してから、アプリコンテンツを定義した XAML [Frame](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.page にPageを移動するのが一般的です。 フレームとページの詳細については、「2 つのページ間のピア ツー ピア ナビゲーション を参照してください。
Frame contentFrame = new Frame(); contentFrame.Navigate(typeof(SecondaryPage));ただし、AppWindowやFrameだけでなく、Pageに任意の XAML コンテンツを表示できます。 たとえば、後で示すように、 ColorPicker などの単一のコントロールのみを表示できます。
XAML コンテンツをの Window プロパティに設定します。
newWindow.Content = contentFrame;Windowを呼び出します。Activate メソッドを使用して新しいウィンドウを表示します。
newWindow.Activate();
Window のインスタンスを追跡する
アプリの他の部分から Window インスタンスにアクセスすることもできますが、 Windowのインスタンスを作成した後は、そのインスタンスへの参照を保持しない限り、他のコードからアクセスする方法はありません。 たとえば、Windowを処理できます。ウィンドウのサイズが変更されたときに UI 要素を再配置するMainPageの SizeChanged イベント。または、Windowのすべての追跡対象インスタンスを閉じる [すべて閉じる] ボタンが表示される場合があります。
この場合は、 WindowId 一意識別子を使用して、 Dictionary内のウィンドウ インスタンスを追跡し、 WindowId を Key として、 Window インスタンスを Valueとして追跡する必要があります。 (TabView タブ のティアアウト 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を処理します。ウィンドウが閉じられたときにActiveWindowsから削除する Closed イベント。
// 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から取得する必要があります。 これは、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];
}
}
}
関連トピック
Windows developer