Prism框架模块化思想、Shell、Region、Moduel
- Prism框架模块化思想、Shell、Region、Moduel
- 简介
- Shell
- Region
- Region的多种注册方式
- 第一种:Xaml方式注册
- 第二种通过C#代码注册
- 创建自己的RegionAdapter
- 定义RegionAdapter
- 注册RegionAdapter
- Region视图切换、Activate
- Navigation
- 基本导航
- 第一种:基本导航
- 第二种:使用参数替代字符串的导航
- 第三种:使用TabControl
- 第四种:判断窗口是否重现还是新增
- 第五种:导航传值
- 第六种:导航日志控制导航
- 第七种:判断导航是否结束
- 第八种:判断能不能导航过去:IConfirmNavigationRequest
- 完整示例:
- 基本导航
- Region的多种注册方式
- Model
- 作用
- 定义
- 注册与发现
- 配置文件注册
- 配合App.config注册Module
- 配合Xml文件注册Moddule
- 代码注册
- 代码基础注册
- 代码按需加载
- 代码IModuleManager任意对象中进行处理
- 自动扫描目录注册
- 配置文件注册
- Dialog弹出窗口
- 改变弹窗样式
- 自定义弹窗
- TabControl示例
Prism框架模块化思想、Shell、Region、Moduel
简介
这是一篇朝夕Jovan老师讲Prism的课堂学习笔记。
-
PrismBootstrapper&PrismApplication【全局资源管控,项目启动】
-
Shell:壳-》Window
-
Region:区域
-
Module:模块(View,ViewModel,Model)
项目的基本结构:Shell=>Region=>Module
Shell
protected override Window CreateShell()
{
return Container.Resolve();
}
Region
如果只更新数据源,UI不变则可以使用prism:RegionManager.RegionContext=""
一般的WPF容器是无法创建Region的,例如:Grid,UniformGrid,DockPanel,Canvas等。
可以创建Region的,例如:
- ContentControl,只能显示一个,所有内容都是堆叠的。
- ItemsControl,所有内容都是栈的形式布局的,类似StackPanel
- ComboBox,所有内容,类似下拉框,下拉列表。
- TabControl,类似TabControl控件
总结:具有RegionAdapter才可以创建Region,可以自定义Region
ContentControl->ContentControlRegionAdapter
ItemsControl->ItemsControlRegionAdapter
ComboBox->SelectorRegionAdapter
TabControl->TabControlRegionAdapter
Region的多种注册方式
第一种:Xaml方式注册
第二种通过C#代码注册
Region中的都是UserControl,所以应该是创建一个ViewA,然后再添加到Region中。
public MainWindow(IRegionManager regionManager)
{
InitializeComponent();
RegionManager.SetRegionName(this.cc, "ContentRegion");
/// 将相关View指定到特定的Region
/// 第一个参数:Region的名称
/// 第二个参数:View的类型
regionManager.RegisterViewWithRegion("ContentRegion", typeof(ViewA));
}
创建自己的RegionAdapter
定义RegionAdapter
public class StackPanelRegionAdapter : RegionAdapterBase
{
public StackPanelRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory) : base(regionBehaviorFactory)
{
}
protected override void Adapt(IRegion region, StackPanel regionTarget)
{
region.Views.CollectionChanged += (se, ev) =>
{
if (ev.Action == NotifyCollectionChangedAction.Add)
{
foreach (UIElement item in ev.NewItems)
{
regionTarget.Children.Add(item);
}
}
};
}
protected override IRegion CreateRegion() => new AllActiveRegion();
}
注册RegionAdapter
public partial class App : PrismApplication
{
protected override Window CreateShell()
{
return Container.Resolve();
}
protected override void ConfigureRegionAdapterMappings(RegionAdapterMappings regionAdapterMappings)
{
base.ConfigureRegionAdapterMappings(regionAdapterMappings);
regionAdapterMappings.RegisterMapping(Container.Resolve());
}
}
Region视图切换、Activate
Activate&Deactivate有针对,并不是所有Adapter适用,例如:ContentControlRegionAdapter可以,如果使用ItemsControlRegionAdapter则会报错。
Region视图切换,Navigation。
- 构造函数注入IRegionManager,IContainerExtension
- 取出Region,_regionManager.Regions["ContentRegion"];
- 添加view
- 导航到指定view
Activate&Deactivate有针对,并不是所有Adapter适用,ContentControlRegionAdapter可以,但是ItemsControlRegionAdapter->报错。
public partial class MainView : Window
{
IRegionManager _regionManager;
IContainerExtension _containerExtension;
ViewB viewB;
public MainView(IRegionManager regionManager, IContainerExtension containerExtension)
{
InitializeComponent();
_regionManager = regionManager;
_containerExtension = containerExtension;
/// Region视图切换
/// Activete&Deactivated
/// 视图切换-》另一种方式:Navigation
this.Loaded += (se, ev) =>
{
var _region = _regionManager.Regions["ContentRegion"];
viewB = _containerExtension.Resolve();
_region.Add(_containerExtension.Resolve());
_region.Add(viewB);
};
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var _region = _regionManager.Regions["ContentRegion"];
_region.Activate(ViewB);
// Activate&Deactivate有针对,并不是所有Adapter适用
// ContentControlRegionAdapter
// ItemsControlRegionAdapter->报错
}
}
判断View是否是活跃状态
- 继承BindableBase, IActiveAware
- 实现
public class ViewAViewModel : BindableBase, IActiveAware,
{
private bool _isActive;
public bool IsActive
{
get => _isActive;
set
{
_isActive = value;
if (value)
{
System.Diagnostics.Debug.WriteLine("ViewA 激活了");
}
else
{
System.Diagnostics.Debug.WriteLine("ViewA 失效了");
}
IsActiveChanged?.Invoke(this, new EventArgs());
}
}
public event EventHandler IsActiveChanged;
}
Navigation
Navigation控制View切换,
- 写View的UI代码
- 写ViewModels的代码
- 写对应的Cmd方法
- 注入View,App.cs 中的RegisterTypes,注入VIew,
containerRegistry.RegisterForNavigation
(); - ViewModel的构造函数中注入IRegionManager,需要的导航到指定的
View:_regionManager.RequestNavigate("ContentRegion", "ViewB");
如果是Module形式的注册,则可以在Module类中通过RegisterForNavigation注册
public class SysModule : IModule { public void OnInitialized(IContainerProvider containerProvider) { } public void RegisterTypes(IContainerRegistry containerRegistry) { containerRegistry.RegisterForNavigation
("mmView"); containerRegistry.RegisterForNavigation (); containerRegistry.RegisterDialog (); } }
基本导航
第一种:基本导航
_regionManager.RequestNavigate("ContentRegion", "ViewB");
第二种:使用参数替代字符串的导航
private DelegateCommand _viewACommand;
public DelegateCommand ViewACommand
{
get
{
if (_viewACommand == null)
_viewACommand = new DelegateCommand((view) =>
{
_regionManager.RequestNavigate("ContentRegion", view);
});
;
return _viewACommand;
}
set { _viewACommand = value; }
}
第三种:使用TabControl
- ViewModel增加属性Title
- 绑定到View
- 和第二中方法的导航一样可以注册到指定的Region内
第四种:判断窗口是否重现还是新增
继承INavigationAware,IsNavigationTarget方法控制
- INavigationAware,实现三个接口方法
- IsNavigationTarget:View是重现(返回True)还是新建(返回False)
- OnNavigatedTo:导航传值,导航日志
- OnNavigatedFrom:从这个页面到那个页面,关注的是出发时机。
第五种:导航传值
-
NavigationWindowViewModel中的ViewACommand传参
-
ViewA中接收参数,OnNavigatedTo中:var param = navigationContext.Parameters["value"];
//NavigationWindowViewModel中的Command
private DelegateCommand _viewACommand;
public DelegateCommand ViewACommand
{
get
{
if (_viewACommand == null)
_viewACommand = new DelegateCommand((view) =>
{
// 导航到 ViewA
// 传值
// 导航某个页面,添加判断,是否是可以导航过去
NavigationParameters param = new NavigationParameters();
param.Add("value", "123");
_regionManager.RequestNavigate("ContentRegion", view,param);
});
;
return _viewACommand;
}
set { _viewACommand = value; }
}
//ViewA中的OnNavigatedTo
public void OnNavigatedTo(NavigationContext navigationContext)
{
// 导航传值
var param = navigationContext.Parameters["value"];
// 历史记录
_journal = navigationContext.NavigationService.Journal;
//_journal.GoForward();
//_journal.GoBack();
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
// 控件View是重现(返回True)还是新建(返回False)
return true;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
// navigationContext可以拿ViewA和ViewB两个对象
// 触发时机
}
第六种:导航日志控制导航
- ViewAViewModel继承INavigationAware,实现对应的OnNavigatedTo
- 向前:journal.GoForward();
- 向后:journal.GoBack();
- ViewAViewModel实现字段IRegionNavigationJournal _journal;
- 添加一个Command调用_journal.GoBack();回到之前的页面
也可以NavigationWindowViewModel构造函数注入,_regionManager也可以达到相同的控制效果
- 构造函数注入:IRegionNavigationService
- 实现ForwordCommand、BackCommand
_regionManager也可以达到相同的控制效果
IRegionManager _regionManager; IRegionNavigationService _regionNavigationService; public NavigationWindowViewModel(IRegionManager regionManager, IRegionNavigationService regionNavigationService) { _regionManager = regionManager; _regionNavigationService = regionNavigationService; } private DelegateCommand _forwordCommand; public DelegateCommand ForwordCommand { get { if (_forwordCommand == null) _forwordCommand = new DelegateCommand(() => { //if (_regionNavigationJournal.CanGoForward) // _regionNavigationJournal.GoForward(); var j = _regionManager.Regions["ContentRegion"].NavigationService.Journal; //var j = _regionNavigationService.Journal; if (j.CanGoForward) j.GoForward(); }); return _forwordCommand; } set { _forwordCommand = value; } } private DelegateCommand _backCommand; public DelegateCommand BackCommand { get { if (_backCommand == null) _backCommand = new DelegateCommand(() => { //var j = _regionNavigationService.Journal; var j = _regionManager.Regions["ContentRegion"].NavigationService.Journal; if (j.CanGoBack) j.GoBack(); }); return _backCommand; } set { _backCommand = value; } }
IRegionNavigationJournal _journal;
public DelegateCommand GoBackCommand { get; set; }
public ViewAViewModel()
{
this.Title = "VIewA";
GoBackCommand = new DelegateCommand(GoBack);
}
private void GoBack()
{
_journal.GoBack();
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
// 导航传值
var param = navigationContext.Parameters["value"];
// 历史记录
_journal = navigationContext.NavigationService.Journal;
//_journal.GoForward();
//_journal.GoBack();
}
第七种:判断导航是否结束
_regionManager.RequestNavigate第三个参数表示导航结束,可以写个Action进行处理,是导航的最后一站。
private DelegateCommand _viewACommand;
public DelegateCommand ViewACommand
{
get
{
if (_viewACommand == null)
_viewACommand = new DelegateCommand((view) =>
{
// 导航到 ViewA
// 传值
// 导航某个页面,添加判断,是否是可以导航过去
NavigationParameters param = new NavigationParameters();
param.Add("value", "123");
_regionManager.RequestNavigate("ContentRegion", view,
new Action((result) =>
{
}),
param);
});
;
return _viewACommand;
}
set { _viewACommand = value; }
}
第八种:判断能不能导航过去:IConfirmNavigationRequest
- 继承接口:IConfirmNavigationRequest
- 实现接口:ConfirmNavigationRequest
public void ConfirmNavigationRequest(NavigationContext navigationContext, Action continuationCallback)
{
bool result = false;
if (MessageBox.Show("数据没保存,是否离开", "确认", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
// 允许导航
result = true;
}
// 不允许导航过来
continuationCallback(result);
}
完整示例:
XAML
注册
public partial class App : PrismApplication
{
protected override Window CreateShell()
{
return Container.Resolve();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation();
containerRegistry.RegisterForNavigation();
}
}
ViewModel
public class NavigationWindowViewModel : BindableBase
{
IRegionManager _regionManager;
IRegionNavigationService _regionNavigationService;
public NavigationWindowViewModel(IRegionManager regionManager, IRegionNavigationService regionNavigationService)
{
_regionManager = regionManager;
_regionNavigationService = regionNavigationService;
}
private DelegateCommand _viewACommand;
public DelegateCommand ViewACommand
{
get
{
if (_viewACommand == null)
_viewACommand = new DelegateCommand((view) =>
{
// 导航到 ViewA
// 传值
// 导航某个页面,添加判断,是否是可以导航过去
NavigationParameters param = new NavigationParameters();
param.Add("value", "123");
_regionManager.RequestNavigate("ContentRegion", view,
new Action((result) =>
{
}),
param);
});
;
return _viewACommand;
}
set { _viewACommand = value; }
}
private DelegateCommand _viewBCommand;
public DelegateCommand ViewBCommand
{
get
{
if (_viewBCommand == null)
_viewBCommand = new DelegateCommand(() =>
{
// 导航到 ViewB
_regionManager.RequestNavigate("ContentRegion", "ViewB");
});
;
return _viewBCommand;
}
set { _viewBCommand = value; }
}
private DelegateCommand _forwordCommand;
public DelegateCommand ForwordCommand
{
get
{
if (_forwordCommand == null)
_forwordCommand = new DelegateCommand(() =>
{
//if (_regionNavigationJournal.CanGoForward)
// _regionNavigationJournal.GoForward();
var j = _regionManager.Regions["ContentRegion"].NavigationService.Journal;
//var j = _regionNavigationService.Journal;
if (j.CanGoForward)
j.GoForward();
});
return _forwordCommand;
}
set { _forwordCommand = value; }
}
private DelegateCommand _backCommand;
public DelegateCommand BackCommand
{
get
{
if (_backCommand == null)
_backCommand = new DelegateCommand(() =>
{
//var j = _regionNavigationService.Journal;
var j = _regionManager.Regions["ContentRegion"].NavigationService.Journal;
if (j.CanGoBack)
j.GoBack();
});
return _backCommand;
}
set { _backCommand = value; }
}
}
需要导航的内容
ViewA.XAML
ViewAViewModel.cs
public class ViewAViewModel : BindableBase, IActiveAware, INavigationAware, IConfirmNavigationRequest
{
IRegionNavigationJournal _journal;
public ViewAViewModel()
{
this.Title = "VIewA";
GoBackCommand = new DelegateCommand(GoBack);
}
private void GoBack()
{
_journal.GoBack();
}
private string _title;
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
public DelegateCommand GoBackCommand { get; set; }
// ===================================================IActiveAware
private bool _isActive;
public bool IsActive
{
get => _isActive;
set
{
_isActive = value;
if (value)
{
System.Diagnostics.Debug.WriteLine("ViewA 激活了");
}
else
{
System.Diagnostics.Debug.WriteLine("ViewA 失效了");
}
IsActiveChanged?.Invoke(this, new EventArgs());
}
}
public event EventHandler IsActiveChanged;
///
/// =====================================================================INavigationAware========
///
///
public void OnNavigatedTo(NavigationContext navigationContext)
{
// 导航传值
var param = navigationContext.Parameters["value"];
// 历史记录
_journal = navigationContext.NavigationService.Journal;
//_journal.GoForward();
//_journal.GoBack();
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
// 控件View是重现(返回True)还是新建(返回False)
return true;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
// navigationContext可以拿ViewA和ViewB两个对象
// 触发时机
}
// ========================================================================IConfirmNavigationRequest
public void ConfirmNavigationRequest(NavigationContext navigationContext, Action continuationCallback)
{
bool result = false;
if (MessageBox.Show("数据没保存,是否离开", "确认", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
// 允许导航
result = true;
}
// 不允许导航过来
continuationCallback(result);
}
}
Model
Model其实是一系列View的集合,是PrismApplication的扩展延伸。
作用
是资源管理的延伸(继承IModule实现的两个方法很好的体现出来),一个程序集里View的注册,有了Module,可以由Module分别进行View的注册,Module再在PrismApplication里进行注册。
定义
- Model中创建View
- Model中创建一个Module的管理类,负责注册:MainModule
- 继承:IModule实现两个接口
- OnInitialized
- RegisterTypes
- 继承:IModule实现两个接口
[Module(ModuleName = "MainModule", OnDemand = false)]
public class MainModule : IModule
{
public void OnInitialized(IContainerProvider containerProvider)
{
var region = containerProvider.Resolve();
//Region
region.RegisterViewWithRegion("LeftDockRegion", typeof(LeftMenuView));
region.RegisterViewWithRegion("TopDockRegion", typeof(HeaderView));
//containerProvider.Resolve().Register();
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
}
}
注册与发现
配置文件注册
配合App.config注册Module
- App.config,配置文件注册与发现Model**
- 添加configSections节点:碰到module节点,就会实例化Prism.Modularity.ModulesConfigurationSection,然后把module加载出来。
- 添加modules节点
- 添加module节点
- assemblyFile:程序集名
- moduleType:通过Type进行反射,程序集全名称+程序集名称
- moduleName:Module名
- startupLoaded:加载的时机
- fals 按需加载,需要了再加载
<?xml version="1.0" encoding="utf-8" ?>
- 注册
- App.xaml.cs中重写ConfigureModuleCatalog
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
base.ConfigureModuleCatalog(moduleCatalog);
moduleCatalog.AddModule();
moduleCatalog.AddModule();
}
- 重新生成Module程序集,并把dll文件复制到Shell主程序文件目录下。
配合Xml文件注册Moddule
- 增加一个ModuleConfig.xml文件
<?xml version="1.0" encoding="utf-8" ?>
- 需要注意App.xaml.cs中的CreateModuleCatalog返回值需要重新写
protected override IModuleCatalog CreateModuleCatalog()
{
return new XamlModuleCatalog("ModuleConfig.xml");
}
代码注册
代码基础注册
- 添加module引用
- App.xaml.cs中ConfigureModuleCatalog注册
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
base.ConfigureModuleCatalog(moduleCatalog);
moduleCatalog.AddModule();
}
代码按需加载
- 添加module引用
- App.xaml.cs中ConfigureModuleCatalog注册
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
base.ConfigureModuleCatalog(moduleCatalog);
moduleCatalog.AddModule(new ModuleInfo
{
ModuleName = "MainModule",
ModuleType = typeof(MainModule.MainModule).AssemblyQualifiedName,
//加载时机 是否按需加载
InitializationMode = InitializationMode.OnDemand
});
}
代码IModuleManager任意对象中进行处理
- 添加module引用
- App.xaml.cs中ConfigureModuleCatalog注册
- 还有一个Module加载完成的事件
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
base.ConfigureModuleCatalog(moduleCatalog);
// 任意对象中进行处理,通过对象的构造函数注入ModuleManager的实例
IModuleManager moduleManager = null;
moduleManager.LoadModule();
moduleManager.LoadModuleCompleted += (se, ev) => { };
}
自动扫描目录注册
- 手动把Module生成的dll,移动到指定目录
- 通过程序集=》属性=》生成=》配置生成路径指定
- 通过程序集=》属性=》生成事件=》配置生成路径
- 定义Module,通过特性控制是否按需加载
[Module(ModuleName = "MainModule", OnDemand = false)]
public class MainModule : IModule
{
public void OnInitialized(IContainerProvider containerProvider)
{
var region = containerProvider.Resolve();
//Region
region.RegisterViewWithRegion("LeftDockRegion", typeof(LeftMenuView));
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
}
}
-
bin.debug中添加目录Modules
-
把module生成的dll,放到目录中
-
App.xaml.cs中ConfigureModuleCatalog注册
protected override IModuleCatalog CreateModuleCatalog()
{
// 扫描目录
return new DirectoryModuleCatalog() { ModulePath = @".\Modules" };
}
Dialog弹出窗口
- 添加一个用户控件(作为弹出窗口的内容)
- Module类中注册Dialog弹出窗口
public class SysModule : IModule
{
public void OnInitialized(IContainerProvider containerProvider){ }
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterDialog();
}
}
- 实现对应的ViewModel,并实现IDialogAware接口
public class UserEditViewModel : IDialogAware
{
public string Title => "用户信息编辑";
public event Action RequestClose;
//是否可以关闭
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
}
public void OnDialogOpened(IDialogParameters parameters)
{
}
}
-
构造函数注入:IDialogService,
- 包括Show、ShowDialog
- 第二个参数可以给弹出窗口传参
- 回调,是窗口状态(在弹出窗口的ViewModel中处理才可以)
-
创建打开命令,通过注入的IDialogService方法ShowDialog打开弹窗
public DelegateCommand OpenDialogCommand { get; private set; }
OpenDialogCommand = new DelegateCommand(() =>
{
DialogParameters param = new DialogParameters();
// View的注册名称 - 参数键值对 - 弹窗回调 - 指定弹出窗口的注册名称
dialogService.ShowDialog("UserEditView", param,
(result) =>
{
});
});
改变弹窗样式
- 通过prism:Dialog.WindowStyle修改弹窗样式,比较少用,一般使用的是自定义弹窗。
自定义弹窗
多个程序或地方使用,创建一个程序集。
- 添加一个窗口
- xaml文件中只处理样式
- .cs文件中继承接口IDialogWindow
public partial class DialogWindow : Window, IDialogWindow
{
public DialogWindow()
{
InitializeComponent();
}
public IDialogResult Result { get; set; }
}
- 在App.xaml.cs中注册
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterDialogWindow();
//containerRegistry.RegisterDialogWindow("DialogWindow");
}
- 命令调用
OpenDialogCommand = new DelegateCommand(() =>
{
DialogParameters param = new DialogParameters();
// View的注册名称 - 参数键值对 - 弹窗回调 - 指定弹出窗口的注册名称
dialogService.ShowDialog("UserEditView", param,
(result) =>
{
});
});
TabControl示例
实现一个TabControl,带关闭按钮。
public class MenuManagementViewModel : BindableBase, INavigationAware
{
private string UriPath = "";
private string _title;
public string Title
{
get { return _title; }
set { _title = value; }
}
public DelegateCommand CloseCommand { get; private set; }
public DelegateCommand SaveCommand { get; private set; }
public MenuManagementViewModel(IRegionManager regionManager, IUnityContainer unityContainer, ICompositeCommands compositeCommands)
{
this.Title = "菜单管理";
CloseCommand = new DelegateCommand((param) =>
{
// 把所在Region里面的当前ViewModel对应的View移除掉
// 操作Region
// 通过Unity顶层容器获取对应的类型
var obj = unityContainer.Registrations.Where(v => v.Name == UriPath).FirstOrDefault();
string name = obj.MappedToType.Name;
if (!string.IsNullOrEmpty(name))
{
var region = regionManager.Regions["ContentRegion"];
var view = region.Views.Where(v => v.GetType().Name == UriPath).FirstOrDefault();
if (view != null)
region.Remove(view);
}
});
SaveCommand = new DelegateCommand(() =>
{
// 菜单保存
});
compositeCommands.DoCommand.RegisterCommand(SaveCommand);
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
UriPath = navigationContext.Uri.ToString();
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return true;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
}
}
public class SysModule : IModule
{
public void OnInitialized(IContainerProvider containerProvider)
{
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation("mmView");
containerRegistry.RegisterForNavigation();
containerRegistry.RegisterDialog();
}
}