「WPF の XAML デザイナーに Prism の Region の内容を表示させたい」をやってみた

C# その2 Advent Calendar 2020 の 7 日目に @t13801206 さんが以下のような記事を書いてくれていました。

[【WPF】XAMLビューアーにRegionの内容を表示させたい【Prism】](https://qiita.com/t13801206/items/d38e9f281481f341b9e2)

確かにデザイナーでも Prism を使ってて Region に何か表示させたいな～と思うのはありますね。なので素直に「へ～、こういう風にも使えるのか、確かに！」って思いました。

上の記事では、以下のように同じ位置にデザイン時に別のものも置くという感じのアプローチでした。

```xml
<!--仮-->
<d:ContentControl>
    <v:PrismUserControl2/>
</d:ContentControl>

<!--本番-->
<ContentControl prism:RegionManager.RegionName="ContentRegion" />
```

これでも要件は達成できているのですが、実際の実行時は Region に指定している ContentControl の Content プロパティに View のインスタンスが設定されるという形になるので、こっちのほうがデザイン時に内容を表示させるという意味では正確かなと思います。

```xml
<ContentControl prism:RegionManager.RegionName="ContentRegion">
    <d:ContentControl.Content>
        <v:PrismUserControl2 />
    </d:ContentControl.Content>
</ContentControl>
```

`d:ContentControl.Content` という名前のタグを書くことでプロパティ要素構文にもデザイン時データを表示させることが出来ます。元のアプローチに対するメリットとしては、より実行時の動作に近いのでデザイナー上での見た目と実際の見た目の乖離が起きにくいというのがあります。

元記事と完全に同じ構成ではありませんが手元でプロジェクトを作って試してみたところ、上記のように指定することでも Region に View が表示させることが確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/f52894d4-c543-13e8-20a6-a5a4261555eb.png)

## .NET Framework は…

元記事内で .NET Framework だと、この方法は使えないと書いてあります。
これは完全に正しくて .NET Framework を窓から投げ捨てて .NET Core 3.1 か .NET 5.0 に移行しましょう…というのではあんまりなので、少し将来の話をしたいと思います。

現時点では、同じ方法を .NET Framework 4.7.2 を指定して作成したプロジェクトのデザイナーでやっても表示されません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/0cf92f84-636b-6032-4636-1411117df77b.png)

ただ今後は、.NET Framework 向けの WPF デザイナーも新しいものに置き換わっていくと思われます。次のバージョンの Visual Studio 2019 16.9 (現時点ではプレビュー) の設定画面には以下のような設定項目があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/b5d23d23-ae9e-5a7e-5217-c7e1abb78010.png)

これにチェックを入れると .NET Framework でも .NET Core や .NET と同じ新しいデザイナーが使われるようになるので、同じように表示されるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/f378abd2-c225-e3de-70ab-473f83ff904b.png)

なので、うまくいけば Visual Studio 2019 16.9 か 16.10 あたりで最新の Visual Studio を使っている人には新しいデザイン時のデータ設定が .NET Framework でも使えるようになると思います。

## 社会人としてのアプローチ方法

今は .NET Core や .NET 5.0 に移行しないとしても、今後のことを考えるとまるっきり無視するというのも出来ないという状態だと思います。さらに .NET Core や .NET 5.0 が Microsoft Update などで配布されるようになりました。社内向けでいうと WSUS で配布ということも出来るようになりますね。

[.NET Core 2.1, 3.1, and .NET 5.0 updates are coming to Microsoft Update](https://devblogs.microsoft.com/dotnet/net-core-updates-coming-to-microsoft-update/)

そのような状況なので、段階的に .NET Core 3.1 や .NET 5.0 に移行するためのステップを踏むというのは必要なことだと思います。（必要だけど実際に社内で、それをやっていいという交渉をして実際にやるための工数を少しでも捻出してもらえるかどうかはまた別の問題ですが…）

移行のステップとしては、プロジェクトファイルの形式を古き良き巨大な XML の csproj 形式から新しい SDK Style のプロジェクトにするというのが最初のステップになります。プロジェクトファイルの形式を変えるだけなので、この時点では .NET Framework をターゲットにしつつ新しいプロジェクトファイルの形式にしただけになります。

これをやるのに一番お手軽な方法は try-convert というツールを使うことです。try-convert を使うことで .NET Core への自動変換をしてくれるのですが、この変換されたプロジェクトの TargetFramework を net47 や net46 に指定することで引き続き .NET Framework をターゲットにし続けることが出来ます。

実際に Qiita 上で try-convert を試してみた方の記事もあります。
[.NET Framework から .NET Core への移植](https://qiita.com/takmot/items/bc0aed5f87feabf94164)

SDK Style のプロジェクトに変換したらしれっと TargetFramework タグを TargetFrameworks に変更して  net46;netcoreapp3.1 のように設定することで 1 つのプロジェクトで .NET Framework と .NET Core や .NET をターゲットにすることが出来ます。ビルド時にどっちにするか選択してビルドすれば OK です。

ここまで頑張ると .NET Core 3.1 と .NET Framework 4.7 の両方を指定したプロジェクトで .NET Core や .NET をターゲットにして VS 2019 でプロジェクトを開くと、しれっと新しいデザイナーが使えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/111836ab-c2a5-9c8a-d1a4-887ed1359619.png)

利用しているサードパーティー製のコントロールが新しいデザイナーに対応していないといった理由などが無い限りは、これで最新のツールの機能を活用しながら .NET Framework のアプリ開発が出来るようになると思います。なので、try-convert かけて net47 をターゲットにしてビルドして実行してみるてエラーが出なければ、.NET Core や .NET とのマルチターゲットに指定してみるというのは手かもしれないなと思いました。

間違えて製品リリース用のビルドを .NET Core とかにしてしまわないように CI/CD とかで .NET Framework 向けのビルドを間違いなくするような仕組みも作っておくと、より安心になるかなとも思います。
CI/CD パイプラインのようなものを用意するのがハードでも SDK Style へのプロジェクトへの変換が出来ていれば `dotnet publish -c Release -f net47` と打ち込むだけで `bin\Release\net47\publish` フォルダーにビルド後の成果物が出来るので最悪バッチファイルとかでもいいです。ここら辺の手間が減るのも古いプロジェクトファイルの形式に比べてメリットになるかなと思います。

## まとめ

元記事のように Prism の Region にデザイン時にも何かを表示するという用途で `d:` でのデザイン時のデータ設定で UserControl を設定するという発想は自分にはなかったのでとても参考になりました。
この記事では、アイデアはそのままに、より実行時の動作に近い設定方を試してみたのと、.NET Frameworkでも将来的に同じようなことが出来るようになるということと、頑張れば今でも .NET Framework を使いつつ新しいデザイナーを使うことも不可能ではないということについて書いてみました。

それでは、良い WPF アプリ開発を！