【WPF】XAMLビューアーにRegionの内容を表示させたい【Prism】


# 2020.12月上旬

C# その2 Advent Calendar 2020 12 / 7

## 21年7月追記

この記事に対して補足していただいたので、リンクを貼ります。
[「WPF の XAML デザイナーに Prism の Region の内容を表示させたい」をやってみた](https://qiita.com/okazuki/items/66fe01843fc91092be13)

## はじめに

私は、Visual Studioを使ってWPFデスクトップアプリケーションを開発しています。
開発の過程で困ったことが起きました。
その困ったことが、**半分解決**したので記事にしようと思いました。

同じことで困っている方の一助になれば幸いです。
また一方で「こうやればいい」というアドバイスも頂ければ嬉しいです。

## 前提

本題へ入る前に前提を説明します。
私が開発するWPFアプリケーションでは[Prismライブラリ](https://prismlibrary.com/)を使っています。
今回はとくに、Prismの機能の1つであるRegion機能[^1]にまつわる話です。
[^1]: [Prism Region Overview](https://prismlibrary.com/docs/wpf/legacy/Navigation.html#prism-region-overview)

`Window`に`UserControl`を埋め込んで表示する場合、私はこう書きます。
`Window`の`ContentControl`タグの箇所に、`PrismUserControl2`が表示されます。

### ビュー

```xml:MainWindow

<Window>
    ...
    <ContentControl prism:RegionManager.RegionName="ContentRegion" />
    ...
</Window>
```

### ビューモデル

```cs:MainWindowViewModel
...
readonly IRegionManager _regionManager;
public MainWindowViewModel(IRegionManager regionManager)
{
    _regionManager = regionManager;
    _regionManager.RegisterViewWithRegion("ContentRegion", typeof(Views.PrismUserControl2));
}
...
```

## 困ったこと（本題）

PrismのRegion機能を使う場合、**XAMLビューアーに`UserControl`が表示されません**。
これが困ったことです。

開発が進むにつれて、「あれ？この`Window`のココってどういう表示なんだっけ？」となります。

### 例をつかって説明します

例として、まず表示させたい`UserControl`をつくります。
単なる青い背景のつまらない画面です。

```xml:PrismUserControl2
<UserControl x:Class="DataContextTest_NETCore3Prism.Views.PrismUserControl2"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:prism="http://prismlibrary.com/"             
             prism:ViewModelLocator.AutoWireViewModel="True"
             Background="Blue" Width="64" Height="64"
             >
    <Grid Margin="10">
        <TextBlock Text="本番" />
    </Grid>
</UserControl>
```

![1204_011.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/77eb2423-54f5-51e7-fdbf-754144a4a92a.png)


青い背景の`UserControl`を`Window`に埋め込みます。

ビュー（ちょっとネタバレを含んでる）

```xml:MainWindow
<Window x:Class="DataContextTest_NETCore3Prism.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="{Binding Title}" Height="350" Width="525" 
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        xmlns:v="clr-namespace:DataContextTest_NETCore3Prism.Views"
        xmlns:vm="clr-namespace:DataContextTest_NETCore3Prism.ViewModels" 
        d:DataContext="{d:DesignInstance Type=vm:MainWindowViewModel}">
    <StackPanel>
        <ContentControl prism:RegionManager.RegionName="ContentRegion" />
    </StackPanel>
</Window>
```

ビューモデル（一部抜粋）

```cs:MainWindowViewModel
readonly IRegionManager _regionManager;
public MainWindowViewModel(IRegionManager regionManager)
{
    _regionManager = regionManager;
    _regionManager.RegisterViewWithRegion("ContentRegion", typeof(Views.PrismUserControl2));
}
```

願わくは、このプレビュー画面が真っ白じゃなくて、UserControl（青い四角）が表示されてほしい。
![1204_010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/63d36524-e387-16a3-f675-807fd301e4d3.png)


もちろん**実行ボタンを押せば、正常にUserControlが表示されます**。
（単なる青い四角を表示させた）
![1204_020.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/c15f1ae6-9ee0-ebbf-3495-b6d424405519.png)

## 半分解決された

WPFの参考文献を検索すると、[okazuki殿](https://qiita.com/okazuki)の記事によくたどり着きます。
そしてだいたいのことが解決されます。

本件は、[@okazuki殿のツイート](https://twitter.com/okazuki/status/1327119651936096256?s=20)をきっかけに解決しました。
関連するマイクロソフトのドキュメントはこちらです：：[Visual Studio の XAML デザイナーでデザイン時のデータを使用する](https://docs.microsoft.com/ja-jp/visualstudio/xaml-tools/xaml-designtime-data?view=vs-2019)

## どうやって半分解決されたか

デザイン時のみ有効な識別子を使うことで、Region機能とは別のルートで`Window`に`UserControl`を表示させました
***表示させたい`UserControl`をXAML内で2回重複して書くことになります***。

デザイン時のみ有効な識別子`d`を使うために、XAMLにおまじないを書いておきます。

おまじない

```cs:MainWindow
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
```

実際のコード

```xml:MainWindow
<Window x:Class="DataContextTest_NETCore3Prism.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="{Binding Title}" Height="350" Width="525" 
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        xmlns:v="clr-namespace:DataContextTest_NETCore3Prism.Views"
        xmlns:vm="clr-namespace:DataContextTest_NETCore3Prism.ViewModels" 
        d:DataContext="{d:DesignInstance Type=vm:MainWindowViewModel}">
    <StackPanel>
        <!--仮-->
        <d:ContentControl>
            <v:PrismUserControl2/>
        </d:ContentControl>

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

デザイン時にも`UserControl`（青い四角）が表示されるようになりました。

![1204_030.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/3f6942a3-c9f3-62f5-4cc2-fe11896efcb7.png)


## 半分解決されていないこと

私が個人的に趣味で行う分には、すべて解決済みです。
しかし、会社人の私としては、上記の方法が使えません。
よって、半分（＝趣味）は解決しましたが、もう半分（出社中の私）としては解決しておりません。

会社にいる私が解決できない理由は、以下2つの要件を満たす環境がないからです。

- 上記の機能は、Visual Studio 2019以降で有効
- 上記の機能は、.NET Coreで有効

前述した公式ドキュメントの要件に書かれています。
>デザイン時のデータには、Visual Studio 2019 バージョン 16.7 以降が必要です。
>.NET Core および UWP 用の Windows Presentation Foundation (WPF) を対象とする Windows デスクトップ プロジェクトがサポートされていること。

（引用元：https://docs.microsoft.com/ja-jp/visualstudio/xaml-tools/xaml-designtime-data?view=vs-2019）

まったく同じことを .NET Framework 4.6.1で行うと、エラーが表示されます。
> MainWindow.xamlに、解決できない型が含まれています。

![1204_040.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/59c72a4f-34fc-c9d0-96c5-e08f00f9967b.png)


はやく .NET5が社内標準になってほしいです。

以上です。
読んでいただきたき、ありがとうございました。