Windows のバージョン 1809 で XAML Islands (MS のドキュメントの翻訳では XAML 諸島) という機能が使えるようになりました。
Windows 10 の UI コントロール (UWP のコントロール) が WPF や Windows Forms アプリケーションで使える夢の機能です。
詳細は公式ドキュメントへ
Windows フォームで試した記事はこちら
今度は WPF アプリケーションで試してみます。
■ NuGet パッケージのインストール
まずは、NuGet で Microsoft.Toolkit.Wpf.UI.XamlHost をインストールします。
以前は、プレリリースを含めるのチェックが必要だった記憶がありますが、今は不要のようです。
■ XAML で XamlHost コントロールを配置
NuGet パッケージをインストールすると、XamlHost コントロールが使えるようになるので、XAML で配置します。
xmlns の追加
これが一番の難関でしょう。Window に次の属性を追加します。
xmlns:xamlhost="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"
Xamlost エレメントの配置
いつものように XAML を書いて行きます。
<xamlhost:WindowsXamlHost Width="300" Height="200" ChildChanged="WindowsXamlHost_ChildChanged" InitialTypeName="Windows.UI.Xaml.Controls.ProgressRing"/>
■ 参照の設定
以前は 6 つほど参照を追加した記憶がありますが、今回は二つだけで済みました。
※もっと多くのコントロールのプロパティなどを設定する場合、他にも参照がいつ様になります
ファイル | 場所 |
---|---|
Windows.Foundation.UniversalApiContract.winmd | C:\Program Files (x86)\Windows Kits\10\References<sdk version>\Windows.Foundation.UniversalApiContract<version> |
Windows.WinMD | C:\Program Files (x86)\Windows Kits\10\UnionMetadata\Facade |
■ プロパティを設定
XamlHost コントロールは、UWP のコントロールを入れるられるコンテナのようなものです。実際に中に配置するコントロールを設定します。今回もまずは ProgressRing を表示してみます。
XamlHost のプロパティ InitialTypeName に Windows.UI.Xaml.Controls.ProgressRing と設定しています。
InitialTypeName で指定したコントロールのプロパティを XML から設定するものであないようです。実際に生成されたイベントの中で設定をします。
XamlHost の ChildChanged イベントにハンドラを設定します。
<xamlhost:WindowsXamlHost Width="300" Height="200" ChildChanged="WindowsXamlHost_ChildChanged" InitialTypeName="Windows.UI.Xaml.Controls.ProgressRing"/>
XAML
XAML は次のようにしました。
<Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp1" xmlns:xamlhost="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost" mc:Ignorable="d" Title="MainWindow" Height="300" Width="400" Background="LightGray"> <Grid> <xamlhost:WindowsXamlHost Width="300" Height="200" ChildChanged="WindowsXamlHost_ChildChanged" InitialTypeName="Windows.UI.Xaml.Controls.ProgressRing"/> </Grid> </Window>
イベントハンドラ
イベントハンドラの中で ProgressRing のプロパティを設定します。
private void WindowsXamlHost_ChildChanged(object sender, EventArgs e) { var host = (Microsoft.Toolkit.Wpf.UI.XamlHost.WindowsXamlHost)sender; var progressRing = (Windows.UI.Xaml.Controls.ProgressRing)host.Child; if (progressRing != null) { progressRing.IsActive = true; progressRing.Width = 300; progressRing.Height = 200; } }
■ 実行
実行してみると、UWP の ProgressRing が表示されました。これで時間のかかる処理を行う際も安心ですね。
ちょっとレイアウトが思っているのと違ってしまいました、こちらは今後検証して行きたいと思います。
■ InkCanvas
UWP のコントロールが使えると聞いて皆が気になるあのコントロール InkCanvas も試してみます。
XamlHost コントロールをもう一つ配置して各種設定をして行きます。
XAML
<Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp1" xmlns:xamlhost="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost" mc:Ignorable="d" Title="MainWindow" Height="300" Width="800" Background="LightGray"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <xamlhost:WindowsXamlHost Grid.Column="0" Width="300" Height="200" ChildChanged="WindowsXamlHost_ChildChanged" InitialTypeName="Windows.UI.Xaml.Controls.ProgressRing"/> <xamlhost:WindowsXamlHost Grid.Column="1" Width="300" Height="200" ChildChanged="WindowsXamlHost_ChildChanged_1" InitialTypeName="Windows.UI.Xaml.Controls.InkCanvas"/> </Grid> </Window>
イベントハンドラ
using System; using System.Windows; namespace WpfApp1 { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void WindowsXamlHost_ChildChanged(object sender, EventArgs e) { var host = (Microsoft.Toolkit.Wpf.UI.XamlHost.WindowsXamlHost)sender; var progressRing = (Windows.UI.Xaml.Controls.ProgressRing)host.Child; if (progressRing != null) { progressRing.IsActive = true; progressRing.Width = 300; progressRing.Height = 200; } } private void WindowsXamlHost_ChildChanged_1(object sender, EventArgs e) { var host = (Microsoft.Toolkit.Wpf.UI.XamlHost.WindowsXamlHost)sender; var inkCanvas = (Windows.UI.Xaml.Controls.InkCanvas)host.Child; if (inkCanvas != null) { inkCanvas.Width = 300; inkCanvas.Height = 200; inkCanvas.InkPresenter.InputDeviceTypes = Windows.UI.Core.CoreInputDeviceTypes.Mouse | Windows.UI.Core.CoreInputDeviceTypes.Pen; } } } }
InlCanvas にマウスで書けるように inkCanvas.InkPresenter.InputDeviceTypes = Windows.UI.Core.CoreInputDeviceTypes.Mouse | Windows.UI.Core.CoreInputDeviceTypes.Pen;
という設定を行っています。
■ 実行
実行して文字を書いてみました。これで最新機能を実装する WPF アプリケーションという要件があっても安心ですね。
■ おまけ .NET Core 3.0
先日 .NET Core 3.0 での Windows フォームアプリケーションでは XAML Islands がまだ使えないませんでした。
デスクトップアプリも .NET Core で作る時代が近づいています。せっかくなので WPF でも XAML 諸島が .NET Core でも使えるか試してみました。
結果は
エラー NU1202 パッケージ Microsoft.Toolkit.Wpf.UI.XamlHost 5.0.1 は netcoreapp3.0 (.NETCoreApp,Version=v3.0) / win-x64 と互換性がありません。 パッケージ Microsoft.Toolkit.Wpf.UI.XamlHost 5.0.1 がサポートするもの: net462 (.NETFramework,Version=v4.6.2)
まだ使えないようです。残念。