Prism简述
- 模块(Module):独立的功能单元,可动态加载。
- 依赖注入(Dependency Injection,DI):通过 IoC 容器(如 Unity、Autofac)管理模块之间的依赖关系。(一个类型是具体的(非抽象的)并且有一个公共构造函数,容器在需要的时候就会自动创建它的实例,即使你没有显式地在容器中注册该类型)
- 区域管理(Region Management):使用
IRegionManager
进行动态 UI 组件加载。 - 事件聚合(Event Aggregator):使用
IEventAggregator
进行模块间通信。
Prism 项目创建(MVVM)
1. 安装Prism
Install-Package Prism.Unity
关于Prism.Core与Prism.Unity的关系
- Prism.Core 是 Prism 的基础库,提供核心功能(事件聚合、命令、MVVM 基础功能等),适用于所有平台(如 WPF、Xamarin)。
- Prism.Unity 依赖于 Prism.Core,并为 Prism 提供 Unity 依赖注入支持,模块化开发、区域管理,适用于 WPF 应用。
2. 创建启动类
2.1 修改App.xaml
① 添加命名空间xmlns:prism="http://prismlibrary.com/"
② 将标签名修改为prism:PrismApplication
③ 删除StartUri
示例代码
<prism:PrismApplication x:Class="YourApp.App"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:YourApp"xmlns:prism="http://prismlibrary.com/"><Application.Resources></Application.Resources>
</prism:PrismApplication>
2.2 修改App.xaml.cs
① 实现PrismApplication类
② 重写CreateShell()与ConfigureModuleCatalog(IModuleCatalog moduleCatalog
③ (可选)重写RegisterTypes(IContainerRegistry containerRegistry)
注:App.xaml.cs中所做的设置均为全局设置
注:App.xaml.cs实例由WPF框架创建,无法通过构造函数依赖注入。若想获取IRegionManager可通过 var regionManager = Container.Resolve<IRegionManager>() 获取,IEventAggregator同理
示例代码
public partial class App : PrismApplication
{/*** 此处设置均为全局设置*//*** 解析并返回主窗口*/protected override Window CreateShell(){return Container.Resolve<MainWindow>();}/*** 注册服务: 依赖注入或导航* 例如: containerRegistry.Register<IMessageService, MessageService>();* 例如: containerRegistry.RegisterSingleton<IMessageService, MessageService>();* 例如: containerRegistry.RegisterForNavigation<ViewA>();* * IRegionManager与IEventAggregator已由Prism注册*/protected override void RegisterTypes(IContainerRegistry containerRegistry){}/*** 模块注册* (* 按需加载* moduleCatalog.AddModule<ModuleA>(InitializationMode.OnDemand);* (在其他地方)* private readonly IModuleManager _moduleManager;* public MyClass(IModuleManager moduleManager)* {* _moduleManager = moduleManager;* }* ......* _moduleManager.LoadModule("ModuleA");* )*/protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog){moduleCatalog.AddModule<ModuleA>();moduleCatalog.AddModule<ModuleB>();}}
3. 创建主窗口
① 添加命名空间 xmlns:prism="http://prismlibrary.com/"
② 添加区域(Region)以动态加载View(例如:<ContentControl prism:RegionManager.RegionName="MainRegion"/>)
注:主窗口至少需要一个区域
示例代码
<Window x:Class="YourApp.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:YourApp"xmlns:prism="http://prismlibrary.com/"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"><Grid><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions><ContentControl prism:RegionManager.RegionName="MainRegion"/><ContentControl prism:RegionManager.RegionName="MessageRegion" Grid.Column="1"/></Grid>
</Window>
4. 创建模块
① 实现IModule接口
② 实现OnInitialized(IContainerProvider containerProvider)与RegisterTypes(IContainerRegistry containerRegistry)
注:模块中所做的设置仅在模块被加载时才生效
示例代码
public class ModuleA : IModule
{/*** 模块中的一切设置均局限于本模块内 仅在模块被加载时生效*/private readonly IRegionManager _regionManager;public ModuleA(IRegionManager regionManager){_regionManager = regionManager;}/*** 模块初始化逻辑*/public void OnInitialized(IContainerProvider containerProvider){// 将 ViewA 区域注入至 MainRegion(或者说将 MainRegion 的初始视图设置为 ViewA)_regionManager.RegisterViewWithRegion("MainRegion", typeof(ViewA));}/*** 注册服务: 依赖注入或导航*/public void RegisterTypes(IContainerRegistry containerRegistry){// 注册导航服务containerRegistry.RegisterForNavigation<ViewA>();containerRegistry.RegisterForNavigation<ViewB>();}
}
5. 创建View与ViewModel
说明:
① View与ViewModel的自动绑定规则:
View位于Views文件夹下,ViewModel位于ViewModels文件夹下
Views文件夹与ViewModels文件夹位于同一命名空间
ViewModel的命名为xxxViewModel(xxx为View的命名)
② BindableBase类:类继承BindableBase类后,通过SetProperty(ref _param, value)
可自动处理 INotifyPropertyChange
注:propp可快捷创建使用SetProperty(ref _param, value)
的属性
View示例代码
<UserControl x:Class="YourApp.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:YourApp.Views"mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"><Grid><Grid.RowDefinitions><RowDefinition/><RowDefinition/></Grid.RowDefinitions><StackPanel><TextBlock Text="This is ViewA" FontSize="24" Panel.ZIndex="-1"/><TextBlock Text="{Binding Message}" FontSize="24" Panel.ZIndex="-1"/></StackPanel><Button Content="Aletr" Height="100" Width="300" FontSize="24" Command="{Binding AlertCommand}"></Button><Button Content="Change To ViewB" Command="{Binding ChangeCommand}" Height="100" Width="300" FontSize="24" Grid.Row="1" ></Button></Grid>
</UserControl>
ViewModel示例代码
public class ViewAViewModel : BindableBase
{private readonly IRegionManager _regionManager;private readonly IEventAggregator _eventAggregator;public ViewAViewModel(IRegionManager regionManager, IEventAggregator eventAggregator){_regionManager = regionManager;_eventAggregator = eventAggregator;_eventAggregator.GetEvent<MessageEvent>().Subscribe(ReceiveMessage);}public ICommand AlertCommand{get => new DelegateCommand(Alert);}public ICommand ChangeCommand{get => new DelegateCommand(Change);}private string _message = "None";public string Message{get => _message;set => SetProperty(ref _message, value);}private void Alert(){new Window().Show();}private void Change(){// 将MainRegion区域导航至ViewB_regionManager.RequestNavigate("MainRegion", "ViewB");}private void ReceiveMessage(string message){Message = message;}
}