Prismを使用したWPFアプリケーション開発で役に立つと思われる項目を一つのアプリケーションにまとめたものを作りました。今回は、モジュールからメニューを追加する方法について書いています。
動作環境:Win10, Visual Studio Community 2017, Prism V7.1.0.431, .NET4.5.2, Prism Template Pack, TraceListeners, WPFLocalizeExtension, OxyPlot
- 1.モジュールにPrismユーザーコントロールを追加
- 2.UserControlをMenuItemに書き換え
- 3.MenuRegionに挿入されるように指定
- 4.M9MenuViewModelのコンストラクターに引数追加
- 5.M9Menu.xaml にMenuItemを追加
- 6.メインアプリのメニューに MenuRegion を設定
- 7.コードで作成する方法
アプリの外観はこんな感じです。

ソリューションはメニューの View が追加された以下のようなものです。

メニューの追加手順は次のようになります。
2.UserControlをMenuItemに書き換え
追加されたM9Menu.xamlをUserControlからMenuItemに変更
Menu.xaml の UserControl を MenuItem に書き換え
<UserControl ....> </UserControl>
>>>修正>>>
<Menutem....> </MenuItem>
Menu.xaml.cs も MenuItem に修正
public partial class M9Menu : UserControl
>>>修正>>>
public partial class M9Menu : MenuItem
3.MenuRegionに挿入されるように指定
MenuRegion に挿入されるように M9Module .cs に記述を追加します。
同時に、M9ViewModel を Menu からアクセスできるように Singleton で登録します。
public class M9Module : IModule
{
public void OnInitialized(IContainerProvider containerProvider)
{
var regionManager = containerProvider.Resolve<IRegionManager>();
regionManager.RegisterViewWithRegion("ContentRegion", typeof(M9));
regionManager.RegisterViewWithRegion("MenuRegion", typeof(M9Menu));
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterSingleton<ViewModels.M9ViewModel>();
}
}
4.M9MenuViewModelのコンストラクターに引数追加
M9MenuViewModelに引数付きコンストラクターを追加し、メニューからM9ViewModelにアクセスできるようにします。
下記設定でVM9経由でメニューからM9ViewModelにバインドが可能となります。
public M9MenuViewModel(M9ViewModel VM)
{
VM9 = VM;
}
private M9ViewModel vM9 ;
public M9ViewModel VM9
{
get { return vM9; }
set { SetProperty(ref vM9, value); }
}
5.M9Menu.xaml にMenuItemを追加
M9Menu.xamlにMenuItemを追加してメニューを構成します。
VisualStudioのGUIにはMenuItemは出てこないので、Blendを使用しましょう。

デザイン時の ViewModel に M9MenuViewModel を設定して、バインドの準備をします。
メニューの Header は直接設定してもいいが、M9ViewModel に設定したプロパティとバインドして多言語化します。
メニューを選択時に実行するコマンドもM9ViewModelに作ってVM9経由でバインドします。

<MenuItem
・・・・・・・・・・・・・・・・
xmlns:ViewModels="clr-namespace:Module9.ViewModels"
mc:Ignorable="d"
prism:ViewModelLocator.AutoWireViewModel="True"
Header="{Binding VM9.Title}"
d:DataContext="{d:DesignInstance {x:Type ViewModels:M9MenuViewModel}}">
<MenuItem Header="{Binding VM9.HeaderMenu1}"
Command="{Binding VM9.CommandMenu1, Mode=OneWay}"
IsEnabled="{Binding VM9.MyCModel.CommandEnable}"/>
<MenuItem Header="{Binding VM9.HeaderMenu2}"
Command="{Binding VM9.CommandMenu2, Mode=OneWay}"
IsEnabled="{Binding VM9.MyCModel.CommandEnable}"/>
</MenuItem>
6.メインアプリのメニューに MenuRegion を設定
メインアプリのメニューに MenuRegion を設定することで、モジュールに作成したメニューが挿入されます。
挿入される順番のコントロールは前回の方法と同じです。
<Menu DockPanel.Dock="Top" Margin="10,0" >
<MenuItem Header="{lex:Loc FILE}"/>
<MenuItem Header="{lex:Loc EDIT}"/>
<MenuItem Header="{lex:Loc MODULE}" prism:RegionManager.RegionName="MenuRegion" Margin="0"/>
</Menu>
7.コードで作成する方法
1.CommonModelにObservableCollection
private ObservableCollection<MenuItem> menuItems = new ObservableCollection<MenuItem>();
public ObservableCollection<MenuItem> MenuItems
{
get { return menuItems; }
set { SetProperty(ref menuItems, value); }
}2.メインアプリでMenuのItemsourceにバインド
3.モジュールのViewModelでMenuItemを作成しCommonModelのObservableCollectionにAdd
作成したサンプルは次の場所に置いてあります。
github.com
次回は、3. ログの保存 について記述したいと思います。