Important
このトピックでは、CommunityToolkit/Microsoft.Toolkit.Win32 GitHub リポジトリの型を使用またはメンションします。 XAML Islands のサポートに関する重要な情報については、そのリポジトリの XAML Islands Notice を参照してください。
Windows 10 バージョン 1903 以降では、UWP 以外のデスクトップ アプリ (C++ デスクトップ (Win32)、WPF、Windows Forms アプリを含む) は、WinRT XAML ホスティング API を使用して、ウィンドウ ハンドル (HWND) に関連付けられている任意の UI 要素で WinRT XAML コントロールをホストできます。 この API を使用すると、UWP 以外のデスクトップ アプリは、WinRT XAML コントロールでのみ使用できる最新の Windows UI 機能を使用できます。 たとえば、UWP 以外のデスクトップ アプリでは、この API を使用して 、Fluent Design System を使用し 、Windows Ink をサポートする WinRT XAML コントロールをホストできます。
WinRT XAML ホスティング API は、開発者が Fluent UI を UWP 以外のデスクトップ アプリに持ち込むための、より広範なコントロールセットの基盤を提供します。 この機能は XAML Islands と呼ばれます。 この機能の概要については、 デスクトップ アプリ (XAML Islands) での WinRT XAML コントロールのホストに関するページを参照してください。
注
XAML Islands に関するフィードバックがある場合は、Microsoft.Toolkit.Win32 リポジトリに新しい問題を作成し、コメントを残します。
WinRT XAML ホスティング API は、デスクトップ アプリに適した選択肢ですか?
WinRT XAML ホスティング API は、デスクトップ アプリで WinRT XAML コントロールをホストするための低レベルのインフラストラクチャを提供します。 一部の種類のデスクトップ アプリには、この目標を達成するために、より便利な代替 API を使用するオプションがあります。
C++ デスクトップ アプリがあり、アプリで WinRT XAML コントロールをホストする場合は、WinRT XAML ホスティング API を使用する必要があります。 これらの種類のアプリに代わるものはありません。
WPFアプリとWindows Forms アプリの場合は、WinRT XAML ホスティング API を直接使用する代わりに、Windows Community Toolkit で XAML Island .NET コントロールを使用することを強くお勧めします。 これらのコントロールは、WinRT XAML ホスティング API を内部的に使用し、キーボード ナビゲーションやレイアウトの変更など、WinRT XAML ホスティング API を直接使用した場合に自分で処理する必要があるすべての動作を実装します。
この記事では、C++ デスクトップ アプリのみが WinRT XAML ホスティング API を使用することをお勧めします。この記事では、主に C++ デスクトップ アプリの手順と例を示します。 ただし、WinRT XAML ホスティング API は、WPFアプリとWindows Forms アプリで使用できます (選択した場合)。 この記事では、Windows Community Toolkit のWPFとWindows Formsのホスト コントロールに関連するソース コードを示して、WinRT XAML ホスティング API がこれらのコントロールでどのように使用されているかを確認します。
XAML ホスティング API の使用方法について説明します
C++ デスクトップ アプリで XAML ホスティング API を使用するためのコード例を使用して、詳細な手順に従う場合は、次の記事を参照してください。
Samples
コードで WinRT XAML ホスティング API を使用する方法は、アプリの種類、アプリの設計、およびその他の要因によって異なります。 この記事では、完全なアプリのコンテキストでこの API を使用する方法を説明するために、次のサンプルのコードを参照します。
C++ デスクトップ (Win32)
次のサンプルは、C++ デスクトップ アプリで WinRT XAML ホスティング API を使用する方法を示しています。
Simple XAML Island サンプル。 このサンプルでは、パッケージ化されていない C++ デスクトップ アプリで WinRT XAML コントロールをホストする基本的な実装を示します。
カスタムコントロールサンプルを含むXAML Island このサンプルでは、パッケージ化された C++ デスクトップ アプリでカスタム WinRT XAML コントロールをホストし、キーボード入力やフォーカス ナビゲーションなどの他の動作を処理する完全な実装を示します。
WPFとWindows Forms
Windows Community Toolkit の WindowsXamlHost コントロールは、WPFおよびWindows Forms アプリで WinRT XAML ホスティング API を使用するための参照サンプルとして機能します。 ソース コードは、次の場所にあります。
コントロールのWPFバージョンについては、ここ。 WPF バージョンは、System.Windows.Interop.HwndHost から派生しています。
コントロールのWindows Formsバージョンについては、go here。 Windows Forms バージョンは、System.Windows.Forms.Control から派生しています。
注
WPFアプリとWindows Forms アプリで直接 WinRT XAML ホスティング API を使用するのではなく、Windows Community Toolkit で XAML Island .NET コントロールを使用することを強くお勧めします。 この記事のWPFとWindows Formsのサンプル リンクは、説明のみを目的としています。
API のアーキテクチャ
WinRT XAML ホスティング API には、これらの主なWindows Runtime型と COM インターフェイスが含まれています。
| 型またはインターフェイス | [説明] |
|---|---|
| WindowsXamlManager | このクラスは、UWP XAML フレームワークを表します。 このクラスは、デスクトップ アプリの現在のスレッドで UWP XAML フレームワークを初期化する 1 つの静的 InitializeForCurrentThread メソッドを提供します。 |
| DesktopWindowXamlSource | このクラスは、デスクトップ アプリでホストしている UWP XAML コンテンツのインスタンスを表します。 このクラスの最も重要なメンバーは Content プロパティです。 このプロパティは、ホストする Windows.UI.Xaml.UIElement に割り当てます。 このクラスには、XAML Islands との間でキーボード フォーカス ナビゲーションをルーティングするための他のメンバーも含まれています。 |
| この COM インターフェイスは AttachToWindow メソッドを提供します。これは、アプリの XAML Island を親 UI 要素にアタッチするために使用します。 すべての DesktopWindowXamlSource オブジェクトは、このインターフェイスを実装します。 | |
| この COM インターフェイスは PreTranslateMessage メソッドを提供します。これにより、UWP XAML フレームワークで特定の Windows メッセージを正しく処理できます。 すべての DesktopWindowXamlSource オブジェクトは、このインターフェイスを実装します。 |
次の図は、デスクトップ アプリでホストされている XAML アイランド内のオブジェクトの階層を示しています。
基本レベルは、XAML アイランドをホストするアプリの UI 要素です。 この UI 要素には、ウィンドウ ハンドル (HWND) が必要です。 XAML Island をホストできる UI 要素の例としては、C++ デスクトップ アプリ用の window などがあります。 WPF アプリの場合は System.Windows.Interop.HwndHost、Windows Forms アプリの場合は System.Windows.Forms.Control。
次のレベルは DesktopWindowXamlSource オブジェクトです。 このオブジェクトは、XAML Island をホストするためのインフラストラクチャを提供します。 コードは、このオブジェクトを作成し、親 UI 要素にアタッチする役割を担います。
DesktopWindowXamlSource を作成すると、このオブジェクトによって、WinRT XAML コントロールをホストするネイティブの子ウィンドウが自動的に作成されます。 このネイティブの子ウィンドウは、ほとんどの場合、コードから抽象化されますが、必要に応じてそのハンドル (HWND) をaccessできます。
最後に、最上位レベルは、デスクトップ アプリでホストする WinRT XAML コントロールです。 これには、Windows SDK によって提供される WinRT XAML コントロールやカスタム ユーザー コントロールなど、 Windows.UI.Xaml.UIElement から派生する任意の UWP オブジェクトを指定できます。
注
デスクトップ アプリで XAML Islands をホストすると、XAML コンテンツの複数のツリーを同じスレッド上で同時に実行できます。 XAML アイランド内の XAML コンテンツのツリーのルート要素をaccessし、それがホストされているコンテキストに関する関連情報を取得するには、XamlRoot クラスを使用します。 CoreWindow、ApplicationView、および Window API は、XAML Islands の正しい情報を提供しません。 詳細については、こちらのセクションをご覧ください。
ベスト プラクティス
WinRT XAML ホスティング API を使用する場合は、WinRT XAML コントロールをホストするスレッドごとに次のベスト プラクティスに従います。
- スレッド用の専用 WindowsXamlManager を作成します。
- ホストする WinRT XAML コントロールごとに、 DesktopWindowXamlSource を作成します。
- 不要になった 各 DesktopWindowXamlSource を破棄します。
- スレッドを終了する前に、スレッドの専用 WindowsXamlManager を破棄します。 この WindowsXamlManager の破棄は非同期であり、スレッドを終了する前に Windows メッセージ キューをドレインする必要があることに注意してください。 これを実行する方法の例については、XAML Islands のサンプルを参照してください。
- 特定のスレッドの WindowsXamlManager を破棄した後、同じスレッドに新しい WindowsXamlManager を 作成することはサポートされていないため、予期しない動作になります。
トラブルシューティング
UWP アプリでの WinRT XAML ホスティング API の使用エラー
| 問題点 | 解決策 |
|---|---|
| アプリが COMException を受け取り、次のメッセージが表示されます。"DesktopWindowXamlSource をアクティブ化できません。 この型は UWP アプリでは使用できません。または"WindowsXamlManager をアクティブ化できません。 この型は、UWP アプリでは使用できません。 | このエラーは、UWP アプリで WinRT XAML ホスティング API を使用しようとしている (具体的には、 DesktopWindowXamlSource 型または WindowsXamlManager 型をインスタンス化しようとしている) ことを示しています。 WinRT XAML ホスティング API は、WPF、Windows Forms、C++ デスクトップ アプリケーションなど、UWP 以外のデスクトップ アプリでのみ使用することを目的としています。 |
WindowsXamlManager 型または DesktopWindowXamlSource 型の使用中にエラーが発生しました
| 問題点 | 解決策 |
|---|---|
| アプリは、次のメッセージで例外を受け取ります。"WindowsXamlManager と DesktopWindowXamlSource は、Windows バージョン 10.0.18226.0 以降を対象とするアプリでサポートされています。 アプリケーション マニフェストまたはパッケージ マニフェストを確認し、MaxTestedVersion プロパティが更新されていることを確認してください。 | このエラーは、アプリケーションが WinRT XAML ホスティング API で WindowsXamlManager 型または DesktopWindowXamlSource 型を使用しようとしたが、アプリが Windows 10 バージョン 1903 以降をターゲットにするようにビルドされたかどうかを OS が判断できないことを示します。 WinRT XAML ホスティング API は、以前のバージョンの Windows 10 でプレビューとして初めて導入されましたが、Windows 10 バージョン 1903 以降でのみサポートされています。この問題を解決するには、アプリの MSIX パッケージを作成してパッケージから実行するか、projectに Microsoft.Toolkit.Win32.UI.SDK NuGet パッケージをインストールします。 |
別のスレッドのウィンドウにアタッチ中にエラーが発生しました
| 問題点 | 解決策 |
|---|---|
| アプリは COMException を受け取り、"AttachToWindow メソッドは、指定した HWND が別のスレッドで作成されたために失敗しました" というメッセージが表示されます。 | このエラーは、アプリケーションが IDesktopWindowXamlSourceNative::AttachToWindow メソッドを呼び出し、別のスレッドで作成されたウィンドウの HWND を渡したことを示します。 このメソッドは、メソッドの呼び出し元のコードと同じスレッドで作成されたウィンドウの HWND を渡す必要があります。 |
別の最上位ウィンドウのウィンドウにアタッチ中にエラーが発生しました
| 問題点 | 解決策 |
|---|---|
| アプリは、次のメッセージで COMException を受け取ります。"AttachToWindow メソッドは失敗しました。指定された HWND が、同じスレッドで AttachToWindow に渡された HWND とは異なる最上位ウィンドウから派生しているためです。" | このエラーは、アプリケーションが IDesktopWindowXamlSourceNative::AttachToWindow メソッドを呼び出し、同じスレッドでこのメソッドの前の呼び出しで指定したウィンドウとは異なるトップレベル ウィンドウから派生するウィンドウの HWND を渡したことを示します。アプリケーションが特定のスレッドで AttachToWindow を呼び出した後、同じスレッド上の他のすべての DesktopWindowXamlSource オブジェクトは、 AttachToWindow の最初の呼び出しで渡されたのと同じトップレベル ウィンドウの子孫であるウィンドウにのみアタッチできます。 すべての DesktopWindowXamlSource オブジェクトが特定のスレッドに対して閉じられると、次の DesktopWindowXamlSource は任意のウィンドウに再度アタッチできます。この問題を解決するには、このスレッド上の他の最上位ウィンドウにバインドされているすべての DesktopWindowXamlSource オブジェクトを閉じるか、この DesktopWindowXamlSource の新しいスレッドを作成します。 |