WPF で Prism と Autofac を使います。
開発環境
Visual Studio Community 2017
.Net Framework 4.6.2
Prism.Autofac 6.3.0
準備
Visual Studio で 新規作成から WPF アプリを選択してプロジェクトを作成します。本記事では プロジェクト名を EduPrismWpfApp としています。
PrismTemplatePack
WPFに限らず Xamrin.Forms など Prism を使って開発をするときに、コントロールを専用のものにしたり、ViewModelLocator の設定など xaml に記述する必要がありますが、これらをテンプレート化してくれている Visual Studio の拡張機能として PrismTemplatePack がありますのでこれを入れておくと少し楽かもしれません。また、今回は使用していませんが Unity や Autofac 用のプロジェクトテンプレートも含まれています。
PrismTemplatePack
https://marketplace.visualstudio.com/items?itemName=BrianLagunas.PrismTemplatePack
パッケージの入手
『ソリューションの Nuget パッケージ管理』を開いて参照タブで Prism.Autofac と検索して一致したものをインストールしてください。 または『パッケージ マネージャーコントロール 』で以下のコマンドを入力してもインストールできます。
Install-Package Prism.Autofac -Version 6.3.0
Prism.Autofac
https://www.nuget.org/packages/Prism.Autofac
Shell の作成
Views フォルダを作成してその中に Shell.xaml をウインドウとして作成します。
<Window x:Class="EduPrismWpfApp.Views.Shell"
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="EduPrismWpfApp">
<Grid>
</Grid>
</Window>
初期状態でプロジェクト直下に自動生成されている MainWindow.xaml は削除しておきます。
Bootstrapper の作成
プロジェクト直下に Bootstrapper.cs を作成して Bootstrapper
クラスに AutofacBootstrapper
を継承させます。ここではShell の登録と表示をおこなうための処理を追加します。
using Autofac;
using EduPrismWpfApp.Views;
using Prism.Autofac;
using System.Windows;
namespace EduPrismWpfApp
{
class Bootstrapper : AutofacBootstrapper
{
protected override void ConfigureContainerBuilder(ContainerBuilder builder)
{
base.ConfigureContainerBuilder(builder);
// Shell の登録
builder.RegisterType<Shell>();
}
protected override DependencyObject CreateShell()
=> Container.Resolve<Shell>();
protected override void InitializeShell()
{
base.InitializeShell();
// Shell を MainWindow に設定して表示する。
Application.Current.MainWindow = (Shell)Shell;
Application.Current.MainWindow.Show();
}
}
}
App.xaml と App.xaml.cs の修正
作成した Bootstrapper
をアプリケーション起動時に呼び出すように App.xaml と App.xaml.cs を修正します。
<Application x:Class="EduPrismWpfApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:EduPrismWpfApp"
Startup="Application_Startup">
<Application.Resources>
</Application.Resources>
</Application>
using System.Windows;
namespace EduPrismWpfApp
{
/// <summary>
/// App.xaml の相互作用ロジック
/// </summary>
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e) =>
// Bootstrapperを起動
new Bootstrapper().Run();
}
}
この状態で実行すると作成した Shell が起動することが確認できると思います。
Module の登録
ソリューションに新しくプロジェクトを作成します。ソリューションエクスプローラでソリューションを右クリックして表示されるコンテクストメニューから「追加」→「新しいプロジェクト」を選択し『WPF ユーザーコントロールライブラリ』を選択してプロジェクトを作成します。本記事ではプロジェクト名を EduPrismWpfApp.Modules.SampleModule としています。普通のクラスライブラリではなく『WPF ユーザーコントロールライブラリ』で作成する理由としては参照設定など少し楽になるからです。作成されたプロジェクトに自動生成されているクラスまたはユーザーコントロールは削除しておきます。最初に作成したプロジェクトと同じように Nuget から Prism.Autofac のパッケージを追加しておいてください。
Model の作成
プロジェクトに Models フォルダを作成してその中に SampleMessageProvider.cs を作成します。今回はサンプルとして、 単純にメッセージ文字列をプロパティとして持っているだけのインターフェイスと、そのインターフェイスを継承したクラスを用意します。
namespace EduPrismWpfApp.Modules.SampleModule.Models
{
public interface ISampleMessageProvider
{
string Message { get; }
}
public class SampleMessageProvider : ISampleMessageProvider
{
public string Message => "Hello Prism App with Autofac";
}
}
ViewModel の作成
プロジェクトに ViewModels フォルダを作成してその中に SamplePageViewModel.cs を作成します。ViewModel ではコンストラクタの引数で先ほど作成した Model のインターフェイスを受取り、読み取り専用のプロパティとして View に公開するようにします。
using EduPrismWpfApp.Modules.SampleModule.Models;
namespace EduPrismWpfApp.Modules.SampleModule.ViewModels
{
public class SamplePageViewModel
{
public ISampleMessageProvider SampleMessageProvider { get; }
public SamplePageViewModel(ISampleMessageProvider sampleMessageProvider)
{
SampleMessageProvider = sampleMessageProvider;
}
}
}
View の作成
プロジェクトに Views フォルダを作成してその中に SamplePage.xaml をユーザーコントロールとして作成します。View では ViewModel で公開されているプロパティからモデルに定義されているメッセージ文字列を Label
要素にバインドして表示するようにします。
<UserControl x:Class="EduPrismWpfApp.Modules.SampleModule.Views.SamplePage"
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">
<Grid>
<Label Content="{Binding SampleMessageProvider.Message}" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
</Grid>
</UserControl>
Module の作成
Prism 用と Autofac 用の二つの Module を作成します。まずは Prism 用の Module としてプロジェクトの直下に SampleModule.cs を作成します。このクラスに Prism.Modularity.IModule
を継承させて Initialize()
で 先ほど作成した View が初期表示されるように処理を追加します。また、画面遷移をおこなうためにコンストラクタの引数で IRegionManager
を受取るようにしておきます。
using EduPrismWpfApp.Modules.SampleModule.Views;
using Prism.Modularity;
using Prism.Regions;
namespace EduPrismWpfApp.Modules.SampleModule
{
/// <summary>
/// Prism用
/// </summary>
public class SampleModule : IModule
{
private IRegionManager RegionManager { get; }
public SampleModule(IRegionManager rm)
{
RegionManager = rm;
}
public void Initialize()
{
// MainRegion に SamplePage を表示
RegionManager.RegisterViewWithRegion("MainRegion", typeof(SamplePage));
}
}
}
Autofac 用の Module としてプロジェクトの直下に SampleModuleRegistry.cs を作成します。このクラスに Autofac.Module
を継承させて Load()
メソッドを override
して Model と View を登録します。
using Autofac;
using EduPrismWpfApp.Modules.SampleModule.Models;
using EduPrismWpfApp.Modules.SampleModule.Views;
namespace EduPrismWpfApp.Modules.SampleModule
{
/// <summary>
/// Autofac 用
/// </summary>
public class SampleModuleRegistry : Module
{
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
// SampleMessageProvider を ISampleMessageProvider として登録
builder.RegisterType<SampleMessageProvider>().As<ISampleMessageProvider>();
// SamplePage を登録
builder.RegisterType<SamplePage>();
}
}
}
Shell.xaml とBootstrapper.cs の修正
Shell.xaml に ContentControl
要素を追加して、 Region 名を指定します。リージョン名の指定は prism:RegionManager.RegionName
に 文字列を設定することでおこなえます。
<Window x:Class="EduPrismWpfApp.Views.Shell"
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="EduPrismWpfApp">
<ContentControl prism:RegionManager.RegionName="MainRegion"/>
</Window>
Bootstrapper クラスに先ほど作成した Module を登録する処理を追加します。追加する内容は以下となります。
-
ConfigureContainerBuilder()
に Autofac 用に作成した Module を登録する処理を追加 -
ConfigureModuleCatalog()
をoverride
して Prism 用に作成した Module を登録する処理を追加
using Autofac;
using EduPrismWpfApp.Views;
using Prism.Autofac;
using Prism.Modularity;
using System.Windows;
namespace EduPrismWpfApp
{
class Bootstrapper : AutofacBootstrapper
{
protected override void ConfigureContainerBuilder(ContainerBuilder builder)
{
base.ConfigureContainerBuilder(builder);
// Shell の登録
builder.RegisterType<Shell>();
// Autofac Module の登録
builder.RegisterModule<Modules.SampleModule.SampleModuleRegistry>();
}
protected override void ConfigureModuleCatalog()
{
base.ConfigureModuleCatalog();
// Prism Module の登録
var mc = (ModuleCatalog)ModuleCatalog;
mc.AddModule(typeof(Modules.SampleModule.SampleModule));
}
protected override DependencyObject CreateShell()
=> Container.Resolve<Shell>();
protected override void InitializeShell()
{
base.InitializeShell();
// Shell を MainWindow に設定して表示
Application.Current.MainWindow = (Shell)Shell;
Application.Current.MainWindow.Show();
}
}
}
この状態で実行すると View が表示されて Model に定義されているメッセージが表示されるのが確認できると思います。