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


2020.12月上旬

C# その2 Advent Calendar 2020 12 / 7

21年7月追記

この記事に対して補足していただいたので、リンクを貼ります。
「WPF の XAML デザイナーに Prism の Region の内容を表示させたい」をやってみた

はじめに

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

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

前提

本題へ入る前に前提を説明します。
私が開発するWPFアプリケーションではPrismライブラリを使っています。
今回はとくに、Prismの機能の1つであるRegion機能1にまつわる話です。
WindowUserControlを埋め込んで表示する場合、私はこう書きます。
WindowContentControlタグの箇所に、PrismUserControl2が表示されます。

ビュー

MainWindow

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

ビューモデル

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

困ったこと(本題)

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

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

例をつかって説明します

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

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>

青い背景のUserControlWindowに埋め込みます。

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

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>

ビューモデル(一部抜粋)

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

願わくは、このプレビュー画面が真っ白じゃなくて、UserControl(青い四角)が表示されてほしい。

もちろん実行ボタンを押せば、正常にUserControlが表示されます
(単なる青い四角を表示させた)

半分解決された

WPFの参考文献を検索すると、okazuki殿の記事によくたどり着きます。
そしてだいたいのことが解決されます。

本件は、@okazuki殿のツイートをきっかけに解決しました。
関連するマイクロソフトのドキュメントはこちらです::Visual Studio の XAML デザイナーでデザイン時のデータを使用する

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

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

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

おまじない

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

実際のコード

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(青い四角)が表示されるようになりました。

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

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

会社にいる私が解決できない理由は、以下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に、解決できない型が含まれています。

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

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