1,介绍。
1.1,什么是Prism?
微软MVVM模式的开源框架。
Prism是由Microsoft社区维护的超轻量级开源框架,其前身为Angel项目。该框架采用模块化架构设计,支持MVVM模式、依赖注入和事件聚合机制,可应用于WPF、Xamarin.Forms、UWP等多个开发平台 。截止2025年5月,Prism已形成包含核心库、平台专用模块的完整技术生态。
1.2,架构
模块化架构
- 支持将应用拆分为独立功能模块,通过IModule接口实现动态加载
- 提供Region区域容器管理系统,实现视图动态组合与界面元素灵活布局
- 支持配置文件、代码声明、目录扫描三种模块加载方式
1.3,实现
依赖注入实现
- 内置IoC容器可管理组件依赖关系,支持Unity/Autofac等多种容器扩展
- ViewModelLocator自动绑定视图与视图模型,通过容器解析依赖实例
- 在WPF项目中使用Bootstrapper初始化容器配置,实现服务注册与组件装配
1.4,导航与通信机制
- FrameNavigationService提供结构化导航服务,支持参数传递与视图生命周期管理
- 事件聚合器(PubSubEvents)实现模块间松耦合通信,支持跨线程消息分发
- DelegateCommand改进异步操作支持,分离UI操作触发与业务逻辑执行
1.5, 跨平台支持
- 2014年发布的Prism 5.0将核心功能拆分为四个独立程序集,支持.NET 4.5/WPF平台按需加载
- 提供可移植类库(PCL)实现视图模型在WPF/[Windows Phone](https://baike.baidu.com/item/Windows Phone/9227600?fromModule=lemma_inlink)/[Windows Store](https://baike.baidu.com/item/Windows Store/9970749?fromModule=lemma_inlink)平台复用
-
Windows Runtime\](https://baike.baidu.com/item/Windows Runtime/1676385?fromModule=lemma_inlink)版本集成会话状态管理、输入验证等特性,适配Windows 8.x/Phone 8.x应用开发
Unity与DryIoc是Prism框架中两种不同的依赖注入容器,它们在功能、使用场景和性能上存在显著差异。以下是两者的主要区别:
1. 功能支持
- Unity :功能更全面,支持在
OnStartup方法中进行服务注册和实例获取。此外,Prism.Unity.Extensions需要较新版本(基础环境需4.6.1)。 - DryIoc :功能相对精简,无法在
OnStartup方法中直接注册或获取实例。其关联的DLL更少,文件占用更小。
2. 多模块支持
- 在多模块项目中,Unity 通过
PrismContainerExtension.Current确保所有模块使用同一容器实例,更适合保证唯一性(如与SQLSugar配合时)。 - DryIoc 在多模块场景下可能需依赖
ContainerLocator.Current,实例一致性较弱。
3. 版本与兼容性
-
Unity :推荐使用8.0及以上版本,因
ContainerLocator.Current的引入更完善。 -
DryIoc:作为Prism 8.0后仅保留的两种容器之一,其集成更轻量,但功能扩展性有限。
- 适用场景
-
Unity:适合需要复杂依赖注入、多模块协同或动态服务注册的场景。
-
DryIoc:适合追求轻量化、快速启动且对容器功能要求不高的项目。
总结
选择时需权衡功能需求与项目规模:若需模块化、动态注册或强一致性,优先选Unity ;若注重轻量化和简洁性,DryIoc更合适。
2,准备
这里以prism.DryIoc容器为例。
2.1,添加Prism.DryIoc

2.2,修改入口文件app.xaml
xaml
<prism:PrismApplication x:Class="PrismBaseObj.App"
xmlns:prism="http://prismlibrary.com/"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:PrismBaseObj"
>
</prism:PrismApplication>
C#
public partial class App : PrismApplication
{
}
3,视图与视图模型的绑定
3.1,设置启动窗口。
C#
public partial class App : PrismApplication
{
protected override Window CreateShell()
{
//设置MainWindow为启动窗口
return Container.Resolve<MainWindow>();
}
}
3.2,关联View(视图)到ViewModel(视图模型)
- 设置附加属性
prism:ViewModelLocator.AutoWireViewModel="True"使视图自动定位到对应的视图模型
xaml
<Window x:Class="PrismBaseObj.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PrismBaseObj"
xmlns:prism="http://prismlibrary.com/"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800" prism:ViewModelLocator.AutoWireViewModel="True">
-
默认情况下,
View与ViewModel的类名存在以下对应关系。-
情况1:位于
Views文件中视图类名为:A(即View类全名包含了Views),自动关联到ViewModels文件夹中(即类全名包含了ViewModels)的类名为A+ViewModel的类,特别需要注意的是:默认情况下查找匹配的是从第一个View开始,所以如果A+ViewModel=*ViewViewModel查找到的是ViewView将出现未找到ViewModel的异常。C#namespace PrismBaseObj.ViewModels { class LoginViewModel { public string UserName { get; set; } = "admin"; } } namespace PrismBaseObj.Views { /// <summary> /// LoginView.xaml 的交互逻辑 /// </summary> public partial class LoginView : Window { public LoginView() { InitializeComponent(); } } -
情况2,视图类B命名空间不包含
Views时,则关联到同一命名空间下类名为B+ViewModel类,例如:PrismBaseObj.MainWindow对应PrismBase.MainWindowViewModelC#//命名空间不包含Views namespace PrismBaseObj { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } } } //命名空间不包含ViewModels namespace PrismBaseObj { class MainWindowViewModel : BindableBase { } } -
情况3,视图类名以View结束时,对应的视图模型为该是视图类名+Model
-
-
自定义视图与视图模型的绑定规则。
C#public partial class App : PrismApplication { protected override Window CreateShell() { //设置启动窗口 return Container.Resolve<Views.LoginView>(); } protected override void ConfigureViewModelLocator() { // base.ConfigureViewModelLocator(); //自定义视图与视图模型的绑定规则。 ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver(viewtype => { //指定视图模型类型为:视图名+ViewModel string typeName = viewtype.FullName + "ViewModel"; Type t = Type.GetType(typeName); return t; }); //直接建立绑定关系 //ViewModelLocationProvider.Register("MainWindow", typeof(MainWindowViewModel)); } }
4,弹窗。
弹窗包含两部分:一部分是弹窗内容,另外部分是弹窗窗口。
4.1,弹窗内容(视图模型需要实现IDialogAware)。
4.1.1,注册弹窗内容。
弹窗内容一般是UserControl或者是Page,不能是窗体,因为弹窗对象会添加一个窗体作为宿主。
C#
public partial class App : PrismApplication
{
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
//注册弹窗
//注册对象只能是page或者是控件不能是窗体,因为其会添添加一个驻在容器窗体
containerRegistry.RegisterDialog<Dialog.SampleDialog>();
}
}
4.1.2,调用弹窗。
xaml
<UserControl x:Class="PrismBaseObj.Dialog.SampleDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:PrismBaseObj.Dialog"
mc:Ignorable="d"
xmlns:prims="http://prismlibrary.com/"
d:DesignHeight="450" d:DesignWidth="800" prims:ViewModelLocator.AutoWireViewModel="True">
<Grid>
<TextBlock Text="示例弹窗"></TextBlock>
</Grid>
</UserControl>
弹窗的视图模型:
C#
namespace PrismBaseObj.Dialog
{
/// <summary>
/// 弹窗的视图模型,需要继承实现IDialogAware
/// </summary>
class SampleDialogViewModel : Prism.Services.Dialogs.IDialogAware
{
public string Title => "示例窗体";
public event Action<IDialogResult> RequestClose;
public bool CanCloseDialog()
{
//是否可以关闭窗体
return true;
}
public void OnDialogClosed()
{
//窗体关闭后发生
}
public void OnDialogOpened(IDialogParameters parameters)
{
}
}
}
xaml
<Window x:Class="PrismBaseObj.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PrismBaseObj"
xmlns:prism="http://prismlibrary.com/"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800" prism:ViewModelLocator.AutoWireViewModel="True">
<Grid>
<Button Content="打开对话框" Command="{Binding OpenDialogCommand}"></Button>
</Grid>
</Window>
C#
namespace PrismBaseObj
{
class MainWindowViewModel : BindableBase
{
//在构造函数中提供服务
public MainWindowViewModel(Prism.Services.Dialogs.IDialogService dialogService)
{
ModifyCommand = new DelegateCommand(DoModifyCammand, CanDomodifyCammand);
OpenDialogCommand = new DelegateCommand(()=>
{
dialogService.Show("SampleDialog", null, a=> {
var t = a.Parameters;
});
});
}
public Prism.Commands.DelegateCommand OpenDialogCommand { get; set; }
}
注意事项
如果启动运行时提示以下异常:

**原因:**前文重写了用于配置视图与视图模型绑定规则的方法ConfigureViewModelLocator()导致。如下:
C#
public partial class App : PrismApplication
{
protected override Window CreateShell()
{
//设置启动窗口
return Container.Resolve<Views.LoginView>();
}
protected override void ConfigureViewModelLocator()
{
// base.ConfigureViewModelLocator();
//自定义视图与视图模型的绑定规则。
ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver(viewtype =>
{
//指定视图模型类型为:视图名+ViewModel
string typeName = viewtype.FullName + "ViewModel";
Type t = Type.GetType(typeName);
return t;
});
//直接建立绑定关系
//ViewModelLocationProvider.Register("MainWindow", typeof(MainWindowViewModel));
}
}
处理办法:
方法1:默认绑定规则,不自定义绑定规则。
方法2:进行如下变更。
C#
protected override void ConfigureViewModelLocator()
{
// base.ConfigureViewModelLocator();
//配置视图模型的定位规则,即视图与哪个视图模型绑定
ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver(viewtype =>
{
//指定视图模型类型为:视图名+ViewModel
string typeName = viewtype.FullName + "ViewModel";
Type t = Type.GetType(typeName);
return t;
});
//告诉ViewModelProvidence用容器创建ViewModel(避免 Activator.CreateInstance 调用无参构造函数)
ViewModelLocationProvider.SetDefaultViewModelFactory((view,viewmodelType)=> {
return Container.Resolve(viewmodelType);
});
//直接建立绑定关系
//ViewModelLocationProvider.Register("MainWindow", typeof(MainWindowViewModel));
}
4.1.3,关闭弹窗。
-
通过窗体的关闭按钮关闭。
-
自定义关闭按钮,关闭。
xaml<Grid> <TextBlock Text="Dialog弹窗" FontSize="20" Foreground="Orange" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock> <Button HorizontalAlignment="Right" VerticalAlignment="Top" Width="80" Height="80" Content="关闭" Command="{Binding CloseCommand}"></Button> </Grid>C#public interface IDialogAware { // // 摘要: // The title of the dialog that will show in the Window title bar. string Title { get; } // // 摘要: // Instructs the IDialogWindow to close the dialog. event Action<IDialogResult> RequestClose; // // 摘要: // Determines if the dialog can be closed. // // 返回结果: // True: close the dialog; False: the dialog will not close bool CanCloseDialog(); // // 摘要: // Called when the dialog is closed. void OnDialogClosed(); // // 摘要: // Called when the dialog is opened. // // 参数: // parameters: // The parameters passed to the dialog void OnDialogOpened(IDialogParameters parameters); } class SampleDialogViewModel : Prism.Services.Dialogs.IDialogAware { public string Title => "SampleDialog示例"; //实现接口定义的事件 public event Action<IDialogResult> RequestClose; public SampleDialogViewModel() { CloseCommand = new Prism.Commands.DelegateCommand(() => { Prism.Services.Dialogs.DialogResult dialogResult = new DialogResult(); dialogResult.Parameters.Add("LogInOk?", true); //调用该委托即可实现窗口的关闭 //IDialogService的 //void Show(string name, IDialogParameters parameters, Action<IDialogResult> callback); //回调方法callback添加在RequestClose上 RequestClose?.Invoke(dialogResult); }); } public bool CanCloseDialog() { return true; } public void OnDialogClosed() { } public void OnDialogOpened(IDialogParameters parameters) { } public Prism.Commands.DelegateCommand CloseCommand { get; set; } }
4.2,弹窗窗体。
4.2.1,自定义默认弹窗窗体样式
xaml
<UserControl x:Class="PrismBaseObj.Dialog.SampleDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:PrismBaseObj.Dialog"
mc:Ignorable="d"
xmlns:prims="http://prismlibrary.com/"
d:DesignHeight="450" d:DesignWidth="800" prims:ViewModelLocator.AutoWireViewModel="True" >
<prims:Dialog.WindowStyle>
<Style TargetType="Window">
<Setter Property="Width" Value="400"></Setter>
<Setter Property="Height" Value="300"></Setter>
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome GlassFrameThickness="-1" UseAeroCaptionButtons="False"></WindowChrome>
</Setter.Value>
</Setter>
</Style>
</prims:Dialog.WindowStyle>
<Grid>
<TextBlock Text="示例弹窗"></TextBlock>
</Grid>
</UserControl>
4.2.2,注册自定义弹窗窗体。
弹窗对象都有一个宿主窗口,而这个窗口都实现了接口:IDialogWindow
-
定义弹窗对象的宿主窗口。
xaml<Window x:Class="PrismBaseObj.HostForm.BorderlessForm" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:PrismBaseObj.HostForm" mc:Ignorable="d" Title="{Binding Title}" Height="450" Width="800" WindowStyle="ThreeDBorderWindow"> </Window>窗口实现接口:
IWindowDialogc#public partial class BorderlessForm : Window,Prism.Services.Dialogs.IDialogWindow { public BorderlessForm() { InitializeComponent(); } public IDialogResult Result { get ; set ; } } -
注册弹窗窗体。
public partial class App : PrismApplication { protected override void RegisterTypes(IContainerRegistry containerRegistry) { //注册弹窗 //注册对象只能是page或者是控件不能是窗体,因为其会添添加一个驻在容器窗体 containerRegistry.RegisterDialog<Dialog.SampleDialog>(); //注册弹窗的窗体 containerRegistry.RegisterDialogWindow<HostForm.BorderlessForm>(); } } -
弹出弹窗时将自动适用注册弹窗窗体,需要注意的是,其样式优先级低于
prims:Dialog.WindowStyle。
5,命令
xaml
<Window x:Class="Command应用.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Command应用"
mc:Ignorable="d"
xmlns:prism="http://prismlibrary.com/"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
Title="{Binding Title}" Height="450" Width="800" prism:ViewModelLocator.AutoWireViewModel="True">
<Grid Background="Transparent">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<!--<i:InvokeCommandAction Command="{Binding ButtonCommand}" ></i:InvokeCommandAction>-->
<prism:InvokeCommandAction Command="{Binding ButtonCommand}" ></prism:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</Grid>
</Window>
C#
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Command应用
{
class MainWindowViewModel:BindableBase
{
public MainWindowViewModel()
{
ButtonCommand = new Prism.Commands.DelegateCommand<object>(obj =>
{
//当为:<prism:InvokeCommandAction Command="{Binding ButtonCommand}"></prism:InvokeCommandAction>
//obj为:System.Windows.Input.MouseButtonEventArgs
//xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
//当为:<i:InvokeCommandAction Command="{Binding ButtonCommand}" ></i:InvokeCommandAction>
//obj为:null
});
}
public Prism.Commands.DelegateCommand<object> ButtonCommand { get; set; }
private string title="示例";
public string Title
{
get { return title; }
set { SetProperty<string>(ref title, value); }
}
}
}
6,事件总线-消息
-
定义事件,该事件需要继承自
EventBase,但EventBase类没有定义Subscribe(),定义了Subscribe()方法的是其派生类PubSubEvent,所以这里继承PubSubEvent。C#//无参 class EventMessage:Prism.Events.PubSubEvent { } //带参 class EventMessageArgs : Prism.Events.PubSubEvent<object> { } -
注入,消息订阅或者发布。
C#class MainWindowViewModel:Prism.Mvvm.BindableBase { public MainWindowViewModel(Prism.Events.IEventAggregator eventAggregator) { // 1,获取消息对象,通过注入的方式获取。 // 2,通过事件对象进行订阅或者发布 // 3,eventAggregator:单例模式 // 总线 事件对象 eventAggregator.GetEvent<EventMessage>().Subscribe(Receive); //有参 eventAggregator.GetEvent<EventMessageArgs>().Subscribe(Receive2); } //无参 private void Receive() { } //有参 private void Receive2(object obj) { } } -
事件总线的过滤。
C#//keepSubscriberReferenceAlive: // 默认为false,表示弱引用。 // true:表示强引用,意味着对象销毁时,需要进行UnSubcribe(取消订阅销毁操作) //ThreadOption : //默认值 :PublisherThread:发布者在什么线程发布,订阅的方法就在哪个线程执行。 //UIThread:不管发布者在哪个线程发布,订阅的方法始终在UI线程执行。 //BackgroundThread:不管发布者在哪个线程发布,订阅的方法始终在BackgroundThread执行。 //Predicate<TPayload> filter:过滤条件 public virtual SubscriptionToken Subscribe(Action<TPayload> action, ThreadOption threadOption, bool keepSubscriberReferenceAlive, Predicate<TPayload> filter);
7,区域化Region
7.1,Prism提供的默认适配器
- ContentControlRegionAdapter
- 适用于:ContentControl
- ItemsControlRegionAdapter
- 适用于:ItemsControl
- SelectorRegionRegionAdapter
- 适用于:ListBox,ListView
- TabControlRegionAdapter
- 使用与:TabControl
示例:
xaml
<UserControl x:Class="lzg.PrismRegion.Base.Views.ViewA"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:lzg.PrismRegion.Base.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Background="ForestGreen">
<TextBlock FontSize="30" Text="ViewA" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
</Grid>
</UserControl>
xaml
<UserControl x:Class="lzg.PrismRegion.Base.Views.ViewB"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:lzg.PrismRegion.Base.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Background="SkyBlue">
<TextBlock FontSize="30" Text="ViewB" Foreground="Blue" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
</Grid>
</UserControl>
在Region中注册视图
c#
namespace lzg.PrismRegion.Base.Views
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow(Prism.Regions.IRegionManager regionManager)
{
InitializeComponent();
//一个区域里可以包含多个视图
regionManager.RegisterViewWithRegion("RegionView", typeof(ViewA));
regionManager.RegisterViewWithRegion("RegionView", typeof(ViewB));
this.Loaded += (obj, e) =>
{
//设置激活的View
var view = regionManager.Regions["RegionView"].Views.FirstOrDefault(item => item.GetType().Name.Equals("ViewB"));
regionManager.Regions["RegionView"].Activate(view);
};
}
}
}
在UI中使用Region
- 使用
ContentControl显示单个View
xaml
<Window x:Class="lzg.PrismRegion.Base.Views.MainWindow"
xmlns:prism="http://prismlibrary.com/"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:lzg.PrismRegion.Base.Views"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<DockPanel>
<Grid DockPanel.Dock="Top" Height="40" >
<TextBlock Text="Header" FontSize="20"></TextBlock>
</Grid>
<StackPanel DockPanel.Dock="Left" Width="80">
<Button Content="ViewA"></Button>
<Button Content="ViewB"></Button>
<Button Content="ViewC"></Button>
</StackPanel>
<Grid>
<!--使用Region-->
<ContentControl prism:RegionManager.RegionName="RegionView"></ContentControl>
</Grid>
</DockPanel>
</Window>
显示效果:

-
使用ItemsControl显示多个视图
xaml<Window x:Class="lzg.PrismRegion.Base.Views.MainWindow" xmlns:prism="http://prismlibrary.com/" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:lzg.PrismRegion.Base.Views" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <DockPanel> <Grid DockPanel.Dock="Top" Height="40" > <TextBlock Text="Header" FontSize="20"></TextBlock> </Grid> <StackPanel DockPanel.Dock="Left" Width="80"> <Button Content="ViewA"></Button> <Button Content="ViewB"></Button> <Button Content="ViewC"></Button> </StackPanel> <Grid> <!--使用Region--> <!--单个显示--> <!--<ContentControl prism:RegionManager.RegionName="RegionView"></ContentControl>--> <!--多个显示--> <ItemsControl prism:RegionManager.RegionName="RegionView"></ItemsControl> </Grid> </DockPanel> </Window>
7.2,自定义区域适配器
-
自定义适配器
C#class UniformRegionAdapter : Prism.Regions.RegionAdapterBase<UniformGrid> { public UniformRegionAdapter(Prism.Regions.IRegionBehaviorFactory factory) : base(factory) { } protected override void Adapt(IRegion region, UniformGrid regionTarget) { region.Views.CollectionChanged += (ea, eg) => { if (eg.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add) { foreach (var item in eg.NewItems) { UIElement element = item as UIElement; regionTarget.Children.Add(element); } } if (eg.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove) { foreach (var item in eg.NewItems) { UIElement element = item as UIElement; regionTarget.Children.Remove(element); } } }; } protected override IRegion CreateRegion() { return new Prism.Regions.Region(); } } -
注册自定义的适配器
C#/// <summary> /// App.xaml 的交互逻辑 /// </summary> public partial class App : Prism.DryIoc.PrismApplication { protected override Window CreateShell() { return Container.Resolve<Views.MainWindow>(); } protected override void RegisterTypes(IContainerRegistry containerRegistry) { } protected override void ConfigureRegionAdapterMappings(RegionAdapterMappings regionAdapterMappings) { base.ConfigureRegionAdapterMappings(regionAdapterMappings); //注册自定义适配器 regionAdapterMappings.RegisterMapping<System.Windows.Controls.Primitives.UniformGrid, UniformRegionAdapter>(); } } -
应用
xaml<Window x:Class="lzg.PrismRegion.Base.Views.MainWindow" xmlns:prism="http://prismlibrary.com/" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:lzg.PrismRegion.Base.Views" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <DockPanel> <Grid DockPanel.Dock="Top" Height="40" > <TextBlock Text="Header" FontSize="20"></TextBlock> </Grid> <StackPanel DockPanel.Dock="Left" Width="80"> <Button Content="ViewA"></Button> <Button Content="ViewB"></Button> <Button Content="ViewC"></Button> </StackPanel> <Grid> <!--使用Region--> <!--单个显示--> <!--<ContentControl prism:RegionManager.RegionName="RegionView"></ContentControl>--> <!--多个显示--> <!--<ItemsControl prism:RegionManager.RegionName="RegionView"></ItemsControl>--> <!--使用自定义的适配器--!> <UniformGrid Columns="3" Rows="2" prism:RegionManager.RegionName="RegionView"></UniformGrid> </Grid> </DockPanel> </Window>
7.3,页面导航-参数传递
7.3.1,导航页面注册
xaml
<UserControl x:Class="lzg.PrismRegion.Navigation.Views.Pages.ViewA"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:lzg.PrismRegion.Navigation.Views.Pages"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Background="GreenYellow">
<TextBlock FontSize="20" Text="ViewA" Foreground="Black"></TextBlock>
</Grid>
</UserControl>
xaml
<UserControl x:Class="lzg.PrismRegion.Navigation.Views.Pages.ViewB"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:lzg.PrismRegion.Navigation.Views.Pages"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Background="Pink">
<TextBlock Text="ViewB" FontSize="20"></TextBlock>
</Grid>
</UserControl>
C#
public partial class App : PrismApplication
{
protected override Window CreateShell()
{
return Container.Resolve<Views.MainWindow>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
//注册导航视图视图,注意视图是控件不是窗体
containerRegistry.RegisterForNavigation(typeof(Views.Pages.ViewA), "ViewA");
containerRegistry.RegisterForNavigation<Views.Pages.ViewB>("ViewB");
}
}
7.3.2,定义支持参数的视图模型
若需要支持参数传递,则页面视图模型需要实现INavigationAware接口
c#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Prism.Regions;
namespace lzg.PrismRegion.Navigation.ViewModels.Pages
{
class ViewAViewModel : INavigationAware
{
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return true;
}
//从这个视图出发
public void OnNavigatedFrom(NavigationContext navigationContext)
{
navigationContext.Parameters.Add("Addr2", "来自于ViewA");
}
//到这个视图
public void OnNavigatedTo(NavigationContext navigationContext)
{
string addr= navigationContext.Parameters.GetValue<string>("Addr");
navigationContext.Parameters.Add("Addr3", "ViewA");
}
}
}
C#
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace lzg.PrismRegion.Navigation.ViewModels.Pages
{
class ViewBViewModel : INavigationAware
{
public bool IsNavigationTarget(NavigationContext navigationContext)
{
//true:表示实例接收导航请求,即多次导航也只有一个实例
return true;
}
//从这个视图出发
public void OnNavigatedFrom(NavigationContext navigationContext)
{
navigationContext.Parameters.Add("Addr2", "来自于ViewB");
}
//到这个视图
public void OnNavigatedTo(NavigationContext navigationContext)
{
//接收来自 RequestNavigate(string regionName, string target, NavigationParameters navigationParameters);
//的navigationParameters,也可以接收来自上一个视图的OnNavigatedFrom(NavigationContext navigationContext)
//如果两个同时传参而key值相同则以 RequestNavigate为准
string addr = navigationContext.Parameters.GetValue<string>("Addr");
}
}
}
7.3.3,导航到视图
C#
class MainWindowViewModel
{
public string Description { get; set; } = "视图导航案例";
public MainWindowViewModel(Prism.Regions.IRegionManager regionManager)
{
OpenCommand = new Prism.Commands.DelegateCommand<string>(viewName =>
{
//视图导航
//方法1,缺点:不能给视图传递参数,重复添加视图
// regionManager.RegisterViewWithRegion("RegionView", viewName);
// object obj = regionManager.Regions["RegionView"].Views.LastOrDefault(view => view.GetType().Name.Equals(viewName, StringComparison.InvariantCultureIgnoreCase));
// regionManager.Regions["RegionView"].Activate(obj);
//方法2,可以传递参数,可选择是否重复添加视图。缺点:ViewModel需要实现接口INavigationAware
//if (viewName == "ViewA")
//{
Prism.Regions.NavigationParameters paras = new Prism.Regions.NavigationParameters();
paras.Add("Addr", "来自于ManiWindow");
regionManager.RequestNavigate("RegionView", viewName, paras);
//}
//else
//{
// regionManager.RequestNavigate("RegionView", viewName);
//}
});
}
public Prism.Commands.DelegateCommand<string> OpenCommand { get; set; }
}
效果:

7.4,导航页面生命周期
页面视图模型实现接口IRegionMemberLifetTime对区域内的视图生命周期进行管理。该接口只有定义一个属性KeepAlive。
KeepAlive:
true表示是失活时保留该视图实例false表示视图非激活状态时销毁该实例。
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Prism.Regions;
namespace lzg.PrismRegion.Navigation.ViewModels.Pages
{
class ViewAViewModel : INavigationAware,IRegionMemberLifetime
{
//视图非激活状态是否保存该实例,false则销毁该实例
public bool KeepAlive => false;
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return true;
}
//从这个视图出发
public void OnNavigatedFrom(NavigationContext navigationContext)
{
navigationContext.Parameters.Add("Addr2", "来自于ViewA");
}
//到这个视图
public void OnNavigatedTo(NavigationContext navigationContext)
{
string addr= navigationContext.Parameters.GetValue<string>("Addr");
navigationContext.Parameters.Add("Addr3", "ViewA");
}
}
}
class ViewBViewModel : INavigationAware,IRegionMemberLifetime
{
public bool KeepAlive => true;
public bool IsNavigationTarget(NavigationContext navigationContext)
{
//true:表示实例接收导航请求,即多次导航也只有一个实例
return true;
}
//从这个视图出发
public void OnNavigatedFrom(NavigationContext navigationContext)
{
navigationContext.Parameters.Add("Addr2", "来自于ViewB");
}
//到这个视图
public void OnNavigatedTo(NavigationContext navigationContext)
{
//接收来自 RequestNavigate(string regionName, string target, NavigationParameters navigationParameters);
//的navigationParameters,也可以接收来自上一个视图的OnNavigatedFrom(NavigationContext navigationContext)
//如果两个同时传参而key值相同则以 RequestNavigate为准
string addr = navigationContext.Parameters.GetValue<string>("Addr");
}
}
效果:
ViewA的KeepAlive==false所以ViewA在非激活状态时销毁;ViewB的KeepAlive==true所以ViewB在非激活状态没有进行销毁。

7.5,导航确认
通过实现接口IConfirmNavigationRequest完成导航确认,需要注意的是:导航确认是在离开本视图时进行,而不是进入本视图时进行
c#
class ViewBViewModel : INavigationAware,IRegionMemberLifetime,IConfirmNavigationRequest
{
#region 接口IRegionMemberLifetime的方法
public bool KeepAlive => true;
#endregion
#region 接口IConfirmNavigationRequest的方法
//从本视图切换到其他视图时执行
//先执行ConfirmNavigationRequest,再执行OnNavigatedFrom
public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
{
if(System.Windows.MessageBox.Show("是否离开此页面","询问", System.Windows.MessageBoxButton.YesNo)== System.Windows.MessageBoxResult.Yes)
{
continuationCallback?.Invoke(true);
}
else
{
continuationCallback?.Invoke(false);
}
}
#endregion
#region 接口INavigationAware的方法
public bool IsNavigationTarget(NavigationContext navigationContext)
{
//true:表示实例接收导航请求,即多次导航也只有一个实例
return true;
}
//从这个视图出发
public void OnNavigatedFrom(NavigationContext navigationContext)
{
navigationContext.Parameters.Add("Addr2", "来自于ViewB");
}
//到这个视图
public void OnNavigatedTo(NavigationContext navigationContext)
{
//接收来自 RequestNavigate(string regionName, string target, NavigationParameters navigationParameters);
//的navigationParameters,也可以接收来自上一个视图的OnNavigatedFrom(NavigationContext navigationContext)
//如果两个同时传参而key值相同则以 RequestNavigate为准
string addr = navigationContext.Parameters.GetValue<string>("Addr");
}
#endregion
}

7.6,Tab区域的Header呈现与关闭
xaml
<Window x:Class="lzg.PrismRegion.Navigation.Views.MainWindow"
xmlns:prism="http://prismlibrary.com/"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:lzg.PrismRegion.Navigation.Views"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<DockPanel>
<Grid Height="40" DockPanel.Dock="Top">
<TextBlock FontSize="20" Text="{Binding Description}"></TextBlock>
</Grid>
<StackPanel DockPanel.Dock="Left" Width="80">
<Button Content="ViewA" Command="{Binding OpenCommand}" CommandParameter="ViewA"></Button>
<Button Content="ViewB" Command="{Binding OpenCommand}" CommandParameter="ViewB"></Button>
</StackPanel>
<Grid>
<TabControl prism:RegionManager.RegionName="RegionView" >
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Header" Value="{Binding DataContext.Title}"></Setter>
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding}" Margin="3" VerticalAlignment="Center"></TextBlock>
<Button Content="×" Command="{Binding RelativeSource={RelativeSource AncestorType=TabItem, Mode=FindAncestor}, Path=Content.DataContext.DeleteCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=TabItem, Mode=FindAncestor}, Path=Content}"
VerticalAlignment="Center" FontSize="16">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border x:Name="Part_Back" Padding="2">
<ContentPresenter></ContentPresenter>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Part_Back" Property="Background" Value="#12000000"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
</Grid>
</DockPanel>
</Window>
c#
<Window x:Class="lzg.PrismRegion.Navigation.Views.MainWindow"
xmlns:prism="http://prismlibrary.com/"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:lzg.PrismRegion.Navigation.Views"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<DockPanel>
<Grid Height="40" DockPanel.Dock="Top">
<TextBlock FontSize="20" Text="{Binding Description}"></TextBlock>
</Grid>
<StackPanel DockPanel.Dock="Left" Width="80">
<Button Content="ViewA" Command="{Binding OpenCommand}" CommandParameter="ViewA"></Button>
<Button Content="ViewB" Command="{Binding OpenCommand}" CommandParameter="ViewB"></Button>
</StackPanel>
<Grid>
<TabControl prism:RegionManager.RegionName="RegionView" >
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Header" Value="{Binding DataContext.Title}"></Setter>
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding}" Margin="3" VerticalAlignment="Center"></TextBlock>
<Button Content="×" Command="{Binding RelativeSource={RelativeSource AncestorType=TabItem, Mode=FindAncestor}, Path=Content.DataContext.DeleteCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=TabItem, Mode=FindAncestor}, Path=Content}"
VerticalAlignment="Center" FontSize="16">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border x:Name="Part_Back" Padding="2">
<ContentPresenter></ContentPresenter>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Part_Back" Property="Background" Value="#12000000"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
</Grid>
</DockPanel>
</Window>
c#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Prism.Regions;
namespace lzg.PrismRegion.Navigation.ViewModels.Pages
{
class ViewAViewModel : INavigationAware,IRegionMemberLifetime
{
public string Title { get; set; } = "ViewA";
public Prism.Commands.DelegateCommand<object> DeleteCommand { get; set; }
//视图非激活状态是否保存该实例,false则销毁该实例
public bool KeepAlive => true;
public ViewAViewModel(Prism.Regions.IRegionManager regionManager)
{
DeleteCommand = new Prism.Commands.DelegateCommand<object>(obj =>
{
//删除当前视图
regionManager.Regions["RegionView"].Remove(obj);
});
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return true;
}
//从这个视图出发
public void OnNavigatedFrom(NavigationContext navigationContext)
{
navigationContext.Parameters.Add("Addr2", "来自于ViewA");
}
//到这个视图
public void OnNavigatedTo(NavigationContext navigationContext)
{
string addr= navigationContext.Parameters.GetValue<string>("Addr");
navigationContext.Parameters.Add("Addr3", "ViewA");
}
}
}
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace lzg.PrismRegion.Navigation.ViewModels
{
class MainWindowViewModel
{
public string Description { get; set; } = "视图导航案例";
public MainWindowViewModel(Prism.Regions.IRegionManager regionManager)
{
OpenCommand = new Prism.Commands.DelegateCommand<string>(viewName =>
{
//视图导航
//方法1,缺点:不能给视图传递参数,重复添加视图
// regionManager.RegisterViewWithRegion("RegionView", viewName);
// object obj = regionManager.Regions["RegionView"].Views.LastOrDefault(view => view.GetType().Name.Equals(viewName, StringComparison.InvariantCultureIgnoreCase));
// regionManager.Regions["RegionView"].Activate(obj);
//方法2,可以传递参数,可选择是否重复添加视图。缺点:ViewModel需要实现接口INavigationAware
//if (viewName == "ViewA")
//{
Prism.Regions.NavigationParameters paras = new Prism.Regions.NavigationParameters();
paras.Add("Addr", "来自于ManiWindow");
regionManager.RequestNavigate("RegionView", viewName, paras);
//}
//else
//{
// regionManager.RequestNavigate("RegionView", viewName);
//}
});
}
public Prism.Commands.DelegateCommand<string> OpenCommand { get; set; }
}
}
效果:

7.7,导航日志
关联接口: IJournalAware
该接口提供了PersistInHistory()方法作用是:为参与导航操作的对象提供了一种选择机制,使其能够避免被添加到"IRegionNavigationJournal"后退栈中。
C#
class ViewBViewModel : Prism.Regions.IJournalAware, Prism.Regions.INavigationAware
{
public string Title { get; set; } = "ViewB";
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return true;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
}
#region IJournalAware接口方法
//确定当前对象是否将被添加到导航日志的后退栈中。
public bool PersistInHistory()
{
//这里设置为false表示不保存B视图的导航历史
return false;
}
#endregion
}
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace lzg.PrismRegion.Journal.ViewModels
{
class MainWindowViewModel
{
Prism.Regions.IRegionNavigationJournal journal;
public MainWindowViewModel(Prism.Regions.IRegionManager regionManager)
{
NavigationCommand = new Prism.Commands.DelegateCommand<string>(viewName =>
{
regionManager.RequestNavigate("ViewRegion", viewName);
Forward.RaiseCanExecuteChanged();
GoBack.RaiseCanExecuteChanged();
});
journal = regionManager.Regions["ViewRegion"].NavigationService.Journal;
Forward = new Prism.Commands.DelegateCommand(DoForward,CanDoForward);
GoBack = new Prism.Commands.DelegateCommand(DoGoBack,CanDoGoBack);
}
private bool CanDoGoBack()
{
return journal.CanGoBack;
}
private bool CanDoForward()
{
return journal.CanGoForward;
// return true;
}
private void DoGoBack()
{
journal.GoBack();
Forward.RaiseCanExecuteChanged();
}
private void DoForward()
{
journal.GoForward();
GoBack.RaiseCanExecuteChanged();
}
public Prism.Commands.DelegateCommand<string> NavigationCommand { get; set; }
public Prism.Commands.DelegateCommand Forward { get; set; }
public Prism.Commands.DelegateCommand GoBack { get; set; }
}
}
8,复合命令CompositeCommand
作用: 一次执行多条命令
类名: Prism.Commands.CompositeCommand
8.1,注册复合指令
目的: 注册一个复合指令实例,使之成为容器。
C#
public partial class App : PrismApplication
{
protected override Window CreateShell()
{
return Container.Resolve<Views.MainWindow>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
//注册导航视图
containerRegistry.RegisterForNavigation<Views.ViewA>("ViewA");
containerRegistry.RegisterForNavigation<Views.ViewB>("ViewB");
//注册复合命令单例
containerRegistry.RegisterSingleton<Prism.Commands.CompositeCommand>();
}
}
8.2,进行容器注入
xaml
<UserControl x:Class="lzg.PrismRegion.Composite.Views.ViewA"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:lzg.PrismRegion.Composite.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Button Content="ViewA" Command="{Binding OpenDialogCommand}" FontSize="20" Foreground="Red"></Button>
</Grid>
</UserControl>
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace lzg.PrismRegion.Composite.ViewModels
{
class ViewAViewModel
{
public ViewAViewModel(Prism.Commands.CompositeCommand compositeCommand)
{
OpenDialogCommand = new Prism.Commands.DelegateCommand(() =>
{
System.Windows.MessageBox.Show("ViewA");
});
//将该命令添加到复合命令中
compositeCommand.RegisterCommand(OpenDialogCommand);
}
public Prism.Commands.DelegateCommand OpenDialogCommand { get; set; }
}
}
xaml
<UserControl x:Class="lzg.PrismRegion.Composite.Views.ViewB"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:lzg.PrismRegion.Composite.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Button Content="ViewB" Command="{Binding OpenDialogCommand}" FontSize="20" Foreground="Green"></Button>
</Grid>
</UserControl>
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace lzg.PrismRegion.Composite.ViewModels
{
class ViewBViewModel
{
public ViewBViewModel(Prism.Commands.CompositeCommand compositeCommand)
{
OpenDialogCommand = new Prism.Commands.DelegateCommand(() =>
{
System.Windows.MessageBox.Show("ViewB");
});
//将该命令添到复合命令中
compositeCommand.RegisterCommand(OpenDialogCommand);
}
public Prism.Commands.DelegateCommand OpenDialogCommand { get; set; }
}
}
8.3,调用复合指令
xaml
<Window x:Class="lzg.PrismRegion.Composite.Views.MainWindow"
xmlns:prism="http://prismlibrary.com/"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:lzg.PrismRegion.Composite.Views"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="137*"/>
<ColumnDefinition Width="655*"/>
</Grid.ColumnDefinitions>
<StackPanel>
<Button Content="打开视图" Command="{Binding OpenCommand}"></Button>
<Button Content="同时弹出对话框" Command="{Binding CompositeCommand}"></Button>
</StackPanel>
<UniformGrid Columns="2" Grid.Column="1">
<ContentControl prism:RegionManager.RegionName="LeftRegion"></ContentControl>
<ContentControl prism:RegionManager.RegionName="RightRegion"></ContentControl>
</UniformGrid>
</Grid>
</Window>
C#
class MainWindowViewModel
{
public MainWindowViewModel(Prism.Commands.CompositeCommand compositeCommand,Prism.Regions.IRegionManager regionManager)
{
CompositeCommand = compositeCommand;
OpenCommand = new Prism.Commands.DelegateCommand(() =>
{
regionManager.RequestNavigate("LeftRegion", "ViewA");
regionManager.RequestNavigate("RightRegion", "ViewB");
});
}
public Prism.Commands.DelegateCommand OpenCommand { get; set; }
public Prism.Commands.CompositeCommand CompositeCommand { get; set; }
}

9,模块化Module
9.1,创建Module
-
创建类库项目
-
引入
Prism.DryIOC -
创建视图与基于
IModule的类Xaml<UserControl x:Class="lzg.PrismModule.ModuleA.ViewA" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:lzg.PrismModule.ModuleA" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <Grid> <TextBlock FontSize="20" Foreground="Red" Text="{Binding Title}"></TextBlock> </Grid> </UserControl>c#using Prism.Regions; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace lzg.PrismModule.ModuleA { class ViewAViewModel : Prism.Regions.INavigationAware { public string Title { get; set; } = "ViewA示例"; public bool IsNavigationTarget(NavigationContext navigationContext) { return true; } public void OnNavigatedFrom(NavigationContext navigationContext) { } public void OnNavigatedTo(NavigationContext navigationContext) { } } }注册导航视图
C#public class ModuleA : Prism.Modularity.IModule { public void OnInitialized(IContainerProvider containerProvider) { } public void RegisterTypes(IContainerRegistry containerRegistry) { //在这里进行导航视图注册 containerRegistry.RegisterForNavigation<ViewA>("ViewA"); } }
9.2,加载Module
9.2.1,基于对象
添加类库引用,基于对象的Module加载,此方法并未解耦
C#
public partial class App : PrismApplication
{
protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
}
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
base.ConfigureModuleCatalog(moduleCatalog);
//方法1,这种需要添加链接库并没有完全解耦
moduleCatalog.AddModule<lzg.PrismModule.ModuleA.ModuleA>();
}
}
9.2.2,基于app.config配置文件
基于app.config配置文件的Module加载,此方法实现了解耦
配置app.config文件
xml
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<!--Prism.Modularity.ModulesConfigurationSection:模块配置节点类-->
<!--Prism.Wpf:模块配置节点类所在的程序集Prism.Wpf.dll-->
<section name="modules" type="Prism.Modularity.ModulesConfigurationSection,Prism.Wpf"/>
</configSections>
<modules>
<!--assemblyFile:程序集文件名;moduleType:程序集限定名-->
<module assemblyFile="dll/lzg.PrismModule.ModuleA.dll"
moduleName="ModuleA"
moduleType="lzg.PrismModule.ModuleA.ModuleA, lzg.PrismModule.ModuleA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
</module>
</modules>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>
Module加载
C#
using Prism.DryIoc;
using Prism.Ioc;
using Prism.Modularity;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace lzg.PrismModule
{
/// <summary>
/// App.xaml 的交互逻辑
/// </summary>
public partial class App : PrismApplication
{
protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
}
protected override IModuleCatalog CreateModuleCatalog()
{
//创建一个基于app.config的Module
return new ConfigurationModuleCatalog();
}
}
}
9.2.3,自动扫描目录
自动扫描指定的目录加载程序集
C#
using Prism.DryIoc;
using Prism.Ioc;
using Prism.Modularity;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace lzg.PrismModule
{
/// <summary>
/// App.xaml 的交互逻辑
/// </summary>
public partial class App : PrismApplication
{
protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
}
protected override IModuleCatalog CreateModuleCatalog()
{
//创建一个基于app.config的Module
// return new ConfigurationModuleCatalog();
// 扫描指定的目录,自动加载目录内的程序集
return new DirectoryModuleCatalog
{
//自动扫描加载Modules文件夹下的程序集
ModulePath="Modules"
};
}
}
}
9.3,应用
xaml
<Window x:Class="lzg.PrismModule.MainWindow"
xmlns:prism="http://prismlibrary.com/"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:lzg.PrismModule"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="37*"/>
<RowDefinition Height="383*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="119*"/>
<ColumnDefinition Width="673*"/>
</Grid.ColumnDefinitions>
<Button Content="加载视图" Command="{Binding OpenCommand}"></Button>
<ContentControl prism:RegionManager.RegionName="ViewRegion" Grid.Row="1" Grid.Column="1"></ContentControl>
</Grid>
</Window>
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace lzg.PrismModule
{
class MainWindowViewModel
{
public MainWindowViewModel(Prism.Regions.IRegionManager regionManager)
{
OpenCommand = new Prism.Commands.DelegateCommand(() =>
{
regionManager.RequestNavigate("ViewRegion", "ViewA");
});
}
public Prism.Commands.DelegateCommand OpenCommand { get; set; }
}
}
效果:
