PrismWPFSample(2)Menuの作り方

Prismを使用したWPFアプリケーション開発で役に立つと思われる項目を一つのアプリケーションにまとめたものを作りました。今回は、モジュールからメニューを追加する方法について書いています。

動作環境:Win10, Visual Studio Community 2017, Prism V7.1.0.431, .NET4.5.2, Prism Template Pack, TraceListeners, WPFLocalizeExtension, OxyPlot

アプリの外観はこんな感じです。

f:id:feynman911:20190627222221j:plain
 
ソリューションはメニューの View が追加された以下のようなものです。

f:id:feynman911:20190630164816j:plain
 

メニューの追加手順は次のようになります。

1.モジュールにPrismユーザーコントロールを追加

メニュー用にPrism UserControl (WPF) を追加します。
M9Menu.xaml と M9MenuViewModel.cs 。

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を使用しましょう。

f:id:feynman911:20190630190132j:plain

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

f:id:feynman911:20190630165806j:plain

<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. ログの保存 について記述したいと思います。