🐕

WPF から Windows App SDK に移行を試してみた

2022/01/09に公開

11 月に 1.0 が出た Windows App SDK ですが UWP への対応を後ろ倒し(時期未定)にして .NET 6 に対応してきたというのには個人的にびっくりしたのですが、.NET 6 で MSIX にパッケージングする形以外にもパッケージングしないものにも対応してカタログ スペック的には結構いい感じに見えます。

ただ、1.0 の時点ではパッケージングしていないものは配布時にランタイムとかを入れないといけなかったりしてちょっとメンドクサイです。

https://docs.microsoft.com/ja-jp/windows/apps/windows-app-sdk/deploy-unpackaged-apps

個人的には MSIX にしてしまいたいところです。ストアでの配布も敷居も結構下がってきてますしね。

ということで?先日 WPF 製のサンプル アプリを Windows App SDk の Windows UI Library 3.0 に移行してみました。WPF のサンプル アプリは Microsoft 公式ドキュメントで .NET Framework から .NET Core 3 へのマイグレーションのチュートリアルとして公開されているアプリケーションの Contoso Expenses になります。

https://docs.microsoft.com/ja-jp/windows/apps/desktop/modernize/modernize-wpf-tutorial-1

このチュートリアルは .NET Core 3 にした後、XAML Islands やトースト通知にも対応したりしているのですが、今回は .NET Core 3 に移行を完了した時点のソースコードを元にして .NET 6 化を行い Windows App SDK (Windows UI Library 3.0) を使う形にしてみました。

元のコード

スタート地点のコードは、以下のフォルダーのコードです。

https://github.com/microsoft/AppConsult-WinAppsModernizationWorkshop/tree/main/Exercise1/02-End

  • プロジェクトの構造 (.NET Framework のプロジェクトもあるけど、それは無視)
    • ContosoExpenses.Data プロジェクト
      • Model レイヤーに相当するプロジェクト。
      • .NET Standard 2.0
        • 依存ライブラリ
          • Bogus
          • LiteDB
          • Microsoft.Windows.Compatibility
    • ContosoExpenses.Core プロジェクト
      • View/ViewModel レイヤーに相当するプロジェクト。
      • .NET Core 3.0
      • 依存ライブラリ
        • MVVM Light Toolkit
        • Unity

移行方法

とりあえず .NET 6 にする必要があります。両方の TargetFramework を net6.0-windows にします。
これは、基本的にビルドが通ることがほとんどだと思います。Contoso Expenses のアプリもエラーが起きることなくビルド出来ました。

不要なパッケージの削除

Microsoft.Windows.Compatibility パッケージは net6.0-windows を指定した時点でレジストリなどの API が呼べるようになっているので不要なので削除します。

依存ライブラリのマイグレーション

次はライブラリを更新していきます。ほとんどは最新版に更新するだけですみますが MVVM Light Toolkit はメンテナンスされていないため何らかのライブラリに移行する必要があります。また、Unity は、ちょっとメンテナンスが今後行われるか不透明なので Microsoft.Extensions.DependencyInjection に移行しました。

MVVM Light Toolkit

MVVM Light Toolkit は現時点ではメンテナンスが行われていないため何らかのライブライに移行が必要です。MVVM Light Toolkit の移行先としては Microsoft.Toolkit.Mvvm が推奨されています。

https://github.com/lbugnion/mvvmlight

Windows Community Toolkit のドキュメントにマイグレーションガイドまで提供されているので、これに沿ってやっていきましょう。基本クラスの置き換えや代替クラスへの置き換えで対応が可能でした。

https://docs.microsoft.com/ja-jp/windows/communitytoolkit/mvvm/migratingfrommvvmlight

Unity

Unity のリポジトリを確認すると以下のように書いてあったので、Unity 固有の機能も使っていない状態なので Microsoft.Extensions.DependencyInjection に移行しました。

https://github.com/unitycontainer/unity

Due to a complete lack of interest from the community to support this project, it has been archived and will no longer be maintained. There will be no more releases of this library.

ViewModelLocator.cs で Unity のコンテナに各種クラスを登録しているので、そこを ServiceCollection と ServiceProvider に置き換えています。

https://github.com/runceel/MigrateToWindowsAppSDKFromWPF/blob/main/src/ContosoExpenses.ViewModels/ViewModelLocator.cs

ViewModel を独立したプロジェクトへ切り出す

WPF のプロジェクトに ViewModel レイヤーも含まれている状態だったので ViewModel レイヤーは個別プロジェクトに抜き出しました。これで .NET 6 の上の WPF で動くようになりました。

Windows App SDK 対応

MVVM パターンで作られているので ViewModel から View への依存が無いので一切 ViewModel に手を入れることなく対応が出来ました。当初は、ViewModel に何かしらの変更が必要になるだろうと思っていたのですが .NET 6 対応とライブラリのアップデート以外で手を入れることはありませんでした…。最終的なコードはこちらから確認できます。

https://github.com/runceel/MigrateToWindowsAppSDKFromWPF

苦労した点 (機能面)

Windows App SDK 1.0 の Windows UI Library 3.0 の段階ではアプリケーションで複数ウィンドウを出すことが出来ません。元のアプリケーションはマルチウィンドウだったので、画面遷移 + ContentDialog による形に画面遷移を組みなおす必要がありました。幸いにもウィンドウの階層がそこまで深くなかったため、画面遷移に ContentDialog という形の画面遷移で対応が可能でした。

ウィンドウが凄くたくさん出るタイプのアプリケーションだと移行が厳しいケースがありそうだと思いました。

最終的な画面遷移は以下のようになりました。

苦労した点 (開発面)

デザイナーが無いので、画面の見た目を確認するために現状は実行しないといけないのが地味に苦痛でした。Xamarin.Forms や MAUI でもそうなのですが、ビルド通さなくても見た目が確認できるのと出来ないのとでは開発しやすさが結構変わります。特に最近の WPF はデザイン時のデータの設定機能も強化されていて快適になっているので、開発体験という面では現状 WPF のほうが強いです。

まとめ

Windows App SDK は今後力を入れていくと言っている点と、.NET 6 にも対応していて UWP のようにセキュアだけど開発者からしたら不便に感じる部分もあるモデルに縛られない(最終的には Win32 と UWP のモデルの両方に対応するはず) ので開発したアプリケーションの形態に応じてチョイスできるので、機能が充実してきたら使いやすそうです。

現状は、マルチウィンドウに未対応 (2022 年 Q2 対応予定) だったりデザイナーも無いのでちょっとしんどいかなというのが正直なところでした。でも、画面遷移 + ContentDialog のような形で問題ないアプリであれば現時点でも使える形にはなってきているなと感じました。

Microsoft (有志)

Discussion