[Xaml Island] 【うまく動かせず断念】.NET core 3.0のWPFでUWPコントロールを使う


もくじ
https://tera1707.com/entry/2022/02/06/144447

やりたいことと、現状のおことわり

お題のとおり、.NET core 3.0のWPFでUWPコントロールを使ってみようとしています。
内容は、勉強のための、かずきさんブログのトレースです。

ただ、かずきさんブログを参考にInkCanvasを試しては見たのですが、現状うまく動かすことができませんでした。
感触としては、HDD容量の節約のために、インストールしていないSDKやツールが多数あるせいで、なにかがうまく動いていないような(個人的な)感触です。

なので、下記をそのまま実施しても、うまく動かない可能性が高いです。
今後、再度トライしたときにメンテしようと思うのと、うまくいかない時の事例としてもしかして参考になればと思い、一応書いた分は残します。(見た方を混乱させてしまったら申し訳ありません)

基本、やったことを上から順番に書いてますが、一番最後に、つまった部分をまとめて書いてます。(うまくいかなくてごちゃごちゃいじくりまわしたので、正確でないかもしれません)

前提

下記のものを使って、2019年7月上旬に試した。
VisualStudio Community2019 Version 16.1.5
.NET Core3.0 preview5
Microsoft.Toolkit.Wpf.UI.Controls 6.0.0-preview5

やったこと

.NET core3.0のインストール

こちらから、インストールした。
https://dotnet.microsoft.com/download/dotnet-core/3.0

試した当時、最新の.NET core3.0はpreview6。(今回試したのは5)
本リリースは2019年11月とのこと。

VisualStudio2019の設定

VisualStudio2019を起動し、
[ツール] > [環境] > [プレビュー機能] > [.NETコアSDKのプレビューを使用する]
にチェックを入れる。

MSの公式ページ?には、
[ツール] > [プロジェクトおよびソリューション] > [.NET Core] >[Use Preview of the .NET core SDK]
にチェックを入れろ、とあるが、そこにはチェックはなかった...
(このページはVS2017の話??)

Microsoft.Windows.SDK.ContractsをNugetからとる

★★今回xaml islandをするうえでは、Microsoft.Windows.SDK.Contractsは不要。
★★下で入れるMicrosoft.Toolkit.Wpf.UI.Controlsに、含まれている。
★★消すのがもったいないので書いた内容は置いておきますが、読み飛ばして下さい。

Windows10 APIを使用するために必要。
試した時点では、Ver 10.0.18362.2002-preview ※プレビュー版

以前は、もう少しややこしい手順が必要だったのが、簡単になった。
ややこしい手順=たぶんこれのこと。

NugetにあるMicrosoft.Windows.SDK.Contractsの説明を訳すと、

Windows 10 WinRT API Packを使用すると、.NET Framework 4.5以降および.NET Core 3.0以降の
ライブラリおよびアプリケーションに最新のWindowsランタイムAPIサポートを追加できます。

このパッケージには、Windows 10バージョン1903までのサポートされている
すべてのWindowsランタイムAPIが含まれています。

とのこと。

Microsoft.Toolkit.Wpf.UI.ControlsをNugetからとる

UWPのコントロールをWPFで使うために必要。
試した時点では Ver 6.0.0-preview5 ※プレビュー版

Program.csを追加する

下記の手順で、追加したProgram.csをスタートアッププログラムに指定し、
スタートアップに指定する。

  • ソリューションを右クリック> [追加] > [新しい項目] > [クラス]を選択し、Program.csと名付ける

- 下のコードを記述する。

Program.cs
using Microsoft.Toolkit.Win32.UI.XamlHost;
using System;

namespace WpfApp30
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            using (new XamlApplication())
            {
                var app = new App();
                app.InitializeComponent();
                app.Run();
            }
        }
    }
}

  • ソリューションのプロパティ > [アプリケーション]の中の[スタートアップオブジェクト]で、作成したProgramクラスを指定する

マニフェストファイルの作成

ソリューションを右クリック> [追加] > [新しい項目] > [アプリケーションマニフェストファイル]を選択し、マニフェストファイルを追加する。(今回は名前は適当)

マニフェストファイルの修正

作成したマニフェストファイルを開き、下記を行う。

  • Windows10が対象OSであることを示すために、Windows10のところのコメントアウトを解除する
  • 対象のバージョンが19H1以降であることを示すために、maxversiontestedを追加して、 ※これをしないと、xaml islandのライブラリが例外を吐くらしい。(かずきさんページ)
  • dpiAwareの設定を追加する

変更前

  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
   ・・・
      <!-- Windows 10 -->
      <!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->

    </application>
  </compatibility>
   ・・・
  <!--
  <application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
    </windowsSettings>
  </application>
  -->

変更後

  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
   ・・・
      <!-- Windows 10 -->
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
      <maxversiontested Id="10.0.18362.0"/>

    </application>
  </compatibility>
   ・・・
  <application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
      <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
    </windowsSettings>
  </application>

マニフェストファイルの指定

ソリューションのプロパティ > [アプリケーション]の中の[リソース] > [マニフェスト]で、作成したマニフェストを指定する。(自動で設定されているかも)

xamlに、UWPのコントロールを配置する

  • まず、xaml Islandの名前空間を追加する
  • その後、下記のようにコードを書き、UWPのコントロールを配置する(今回は、UWPのInkCanvasを置く)
MainWindow.xaml
<Window x:Class="WpfApp33.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:WpfApp33"
        xmlns:toolkit="clr-namespace:Microsoft.Toolkit.Wpf.UI.Controls;assembly=Microsoft.Toolkit.Wpf.UI.Controls"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <toolkit:InkCanvas  />
    </Grid>
</Window>

ここまでの通りやってみましたが、うまくうごかなかった..

うまく動かない、というのは、ビルドはできて、アプリ実行(F5)もできるが、ウインドウになにも表示されない状態になる(InkCanvasはもちろん、試しにその他配置したもの(Buttonなど)もすべて見えない)、という感じ。
(InkCanvasをはずすと、その他のButtonなどは出てくる)

しばらく寝かせて、近く再トライしたい。

かずきさんデモ/ブログのとおりにやってみて、つまづいた部分

  • 実験当時、Microsoft.Toolkit.Wpf.UI.Controlsは最新は6.0.0-preview6.3だったが、そのVerだとProgram.csがうまくビルドできなかったので、かずきさんがデモされているpreview5を使用した。(preview6.3だとXamlApplicationクラスがnewできない)
  • .NETCore3.0preview6とMicrosoft.Toolkit.Wpf.UI.Controls 6.0.0-preview5の組み合わせだと、こんなエラーがでる??
  • 上のエラーは、.NETcore3.0とNugetしたtoolkitのバージョンの組み合わせではなく、Windows10のバージョンが新しくないため???こちら参照(When I run the application, I get an InvalidCastException. とあるところ)
  • 今使っていたWindows10は「1809」だった。どうも「1903」以降でないとうごかないっぽい。
  • 1809→1903にWindowsUpdateしてみて試す→Updateしたが、だめだった。状況変わらず。
  • 「ユニバーサルWindowsプラットフォーム開発」のWindows 10 SDK (10.0.18362.0)がインストールされていない。SDKが足りていないから動かないのかも?→インストールしたが、動かず。(ビルドはできて、アプリ実行もできるが、ウインドウになにも表示されない状態になる(InkCanvasはもちろん、その他に配置したものもすべて見えない))
  • .NET core3.0のせいかも?→.NET Framework(たしか4.7.2)に変えて同じことをやってみたが、同じような現象になった。(ビルドできてWindowはでるが、真っ白なWindowになる)
  • ここまでで、一旦断念...

その他不明点メモ

  • Windows10 API = UWP APIなのか??用語の理解が追い付いてない。
  • あとWindows Runtime APIも。同じものを指してる??

参考

公式ページ
https://docs.microsoft.com/ja-jp/windows/apps/desktop/modernize/xaml-islands

公式ブログ
https://techcommunity.microsoft.com/t5/Windows-Dev-AppConsult/Using-XAML-Islands-on-Windows-10-19H1-fixing-the-quot/ba-p/376330#M117