目录
一、安装&新建项目
1. Nuget安装prism.core,prism.wpf,prism.unity
2.可安装vs扩展包快速创建项目:Prism Template Pack
扩展 --> 管理扩展 -->联机,搜索Prism Template Pack,下载完成后重启VS安装,
tips: vs2019下载扩展时,会出现下载失败的情况,可用电脑连接手机热点下载
3.新建项目,选择Prism Blank App(.NET Core),容器有两种(Unity,Dryloc),本文用Unity容器,
App.xaml
public partial class App
{
//重写CreateShell方法,在App.xaml文件中,不再设置StartupUri
protected override Window CreateShell()
{
//使用容器创建主窗体
return Container.Resolve<MainWindow>();
}
//给容器中注册对象
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
}
}
二、View与ViewModel的绑定
- View中引入名称空间:
xmlns:prism="http://prismlibrary.com/"
- 设置为自动关联:
prism:ViewModelLocator.AutoWireViewModel="True"
tips: 1. 必须是Views和ViewModels目录
2. 需要保证命名规范的正确性
① View可以以View结尾,也可以不写
② ViewModel必须以View的名称+”ViewModel”进行命名
3. eg: Views: Main, HomeView;
ViewModel:MainViewModel, HomeViewModel
3. 默认的查找逻辑的源码
var viewName = viewType.FullName;
viewName = viewName.Replace(".Views.", ".ViewModels.");
var viewAssemblyName = viewType.GetTypeInfo().Assembly.FullName;
var suffix = viewName.EndsWith("View") ? "Model" : "ViewModel";
var viewModelName = String.Format(CultureInfo.InvariantCulture, "{0}{1}, {2}", viewName, suffix, viewAssemblyName);
return Type.GetType(viewModelName);
三、属性通知
1. ViewModel继承BindableBase抽象类,实现INotifyPropertyChanged接口,使用SetProperty
public class MainWindowViewModel : BindableBase
{
private string _title;
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
}
四、命令
1. 添加引用 using Prism.Commands;
2. 使用DelegateCommand类,实现了ICommand接口,eg
public class RegionAViewModel:BindableBase
{
//该属性控制按钮是否可用
private bool _isEnable = true;
public bool IsEnable
{
get { return _isEnable; }
set { SetProperty<bool>( ref _isEnable, value); }
}
public DelegateCommand ShowCommand { get; private set; }
public DelegateCommand StartCommand { get; private set; }
public DelegateCommand<string> CannelCommand { get; private set; }
public RegionAViewModel()
{
//命令绑定到方法Show()
ShowCommand = new DelegateCommand(Show);
//调用了ObservesCanExecute方法,这个方法有一个Fun委托参数用来表示该命令是否可以执行(表现在界面上就是按钮灰调),
StartCommand = new DelegateCommand(Start).ObservesCanExecute(() => IsEnable);
//带string参数 这里直接写true,表示按钮一直可用
CannelCommand = new DelegateCommand<string>(Cannel).ObservesCanExecute(() => true);
}
private void Show() { }
private void Start(){ }
private void Cannel(string str) { }
}
五、Region(区域)
1. 概念:在Prism当中,一个页面我们可以不再为其固定显示的内容,而这种概念变成了区域 (Region)划分的概念。将页面显示的区域划分成N个Region,每一个Region将动态分配区域。 它将负责承担我们的UI组件或者控件。
2. 注册使用,eg
在MainWindow.xaml.cs中,绑定region与view
public partial class MainWindow : Window
{
//因为MainWindow对象是我们在App类中使用容器解析得到的,那么它需要的依赖IRegion也会自动被创建
//通过构造函数传入IRegionManager参数
public MainWindow(IRegionManager regionManager, IContainerExtension container )
{
InitializeComponent();
//绑定region和view 参1:region的名字 参2:region要加载的view
regionManager.RegisterViewWithRegion("RegionA", typeof(RegionAView));
regionManager.RegisterViewWithRegion("RegionB",typeof(RegionBView));
}
}
在MainWindow.xaml中声明,RegionName即为之前注册的名字,这样定义的RegionA区域显示的就是RegionAView的内容
<ContentControl Grid.Row="0" prism:RegionManager.RegionName="RegionA"/>
六、Navigation(导航)
1. Prism用Navigation功能来进行页面切换、导航, 将View注册到导航中
2. 将View注册到导航中,App.xaml.cs
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
//View对象注册为单例对象
containerRegistry.RegisterSingleton<RegionAView>();
//注册导航页面,其中第一个参数是View的类型,第二个参数是ViewName(可省略,则默认为View类型的类名)
containerRegistry.RegisterForNavigation(typeof(RegionAView),"ViewA");
}
3. 添加按钮触发导航
<!--为Navigation注册的Region-->
<ContentControl Grid.Row="3" prism:RegionManager.RegionName="Navigation"/>
<Button Content="导航" Width="100" Command="{Binding NavigationCommand}" CommandParameter="ViewA"/>
4. 绑定命令,请求导航
public class MainWindowViewModel : BindableBase
{
public DelegateCommand<string> NavigationCommand { get; private set; }
private IRegionManager RegionManager;
public MainWindowViewModel(IRegionManager regionManager)
{
RegionManager = regionManager;
NavigationCommand = new DelegateCommand<string>(Navigation);
}
private void Navigation(string page)
{
//请求导航时的携带的参数
NavigationParameters parameters = new NavigationParameters();
parameters.Add("param", "参数");
//请求导航,即region显示之前注册的view
//参数1:RegionName,:参数2:我们前面注册的ViewName,参数3:请求导航完成的回调函数,参数4:请求导航时的参数
RegionManager.RequestNavigate("Navigation", page, NavigationCallback, parameters);
}
private void NavigationCallback(NavigationResult result)
{
Debug.WriteLine("回调");
Debug.WriteLine(result.Context.Uri);
Debug.WriteLine(result.Result.Value);
}
}
七、Dialog(对话框)
1. Prism提供了一组对话服务,封装了常用的对话框组件的功能,使View用show/showdialog弹出
2. 注册Dialog,App.xaml.cs
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
//注册Dialog, <DialogView>:使用的view "DialogViewName":起的DialogName
containerRegistry.RegisterDialog<DialogView>("DialogViewName");
}
3. 添加按钮
<Button Content="Dialog" Width="100" Command="{Binding DialogCommand}"/>
4. 绑定命令,触发dialog
public class MainWindowViewModel : BindableBase
{
public DelegateCommand DialogCommand { get; private set; }
private IDialogService DialogService;
public MainWindowViewModel(IRegionManager regionManager, IDialogService dialogService)
{
DialogService = dialogService;
DialogCommand = new DelegateCommand(DialogShow);
}
private void DialogShow()
{
IDialogParameters parameters = new DialogParameters();
parameters.Add("param", "dialog携带参数");
//打开对话框,参数1:之前注册的DialogName, 参数2:传递给对话框的参数, 参数3:对话框被关闭时的回调函数
DialogService.ShowDialog("DialogViewName", parameters, DialogCallback);
}
private void DialogCallback(IDialogResult result)
{
//获取对话框的结果
ButtonResult btnResult = result.Result;
Debug.WriteLine(btnResult.ToString());
//对话框关闭时传的参数
string str = result.Parameters.GetValue<string>("param");
Debug.WriteLine(str);
}
}
5. 使用对话框的view相对应的viewmodel实现接口IDialogAware,来监控对话框
public class DialogViewModel : BindableBase,IDialogAware
{
private string _param;
public string Param
{
get { return _param; }
set { SetProperty(ref _param, value); }
}
//Yes按钮
public DelegateCommand YesCommand { get; private set; }
//No按钮
public DelegateCommand NoCommand { get; private set; }
public DialogViewModel()
{
Param = "Hello DialogView";
YesCommand = new DelegateCommand(YesDo);
NoCommand = new DelegateCommand(NoDo);
}
private void YesDo()
{
IDialogParameters parameters = new DialogParameters();
parameters.Add("param", "dialog点击yes关闭携带的参数");
//点击Yes按钮的时候关闭对话框,并且传递对话框结果(结果中还可以带参数)
RequestClose?.Invoke(new DialogResult(ButtonResult.OK, parameters));
}
private void NoDo()
{
RequestClose?.Invoke(new DialogResult(ButtonResult.Cancel));
}
#region IDialogAware所属方法
//表示对话框窗体的标题。(打开对话框的时候,其实还是将该用户控件装载到了一个窗体中)
public string Title => "DialogTest";
//触发这个事件去关闭对话框,这个事件的订阅就是在ShowDialog时声明的当对话框关闭后的回调函数。
public event Action<IDialogResult> RequestClose;
//如果返回true,则表示可以关闭对话框,否则不可以关闭对话框。(这时按钮不会变灰,但是点击无效。即使触发RequestClose也会无效)
public bool CanCloseDialog()
{
return true;
}
//当对话框被关闭的时候触发这个方法(无论是点击关闭按钮还是触发事件)
public void OnDialogClosed()
{
Debug.WriteLine($"对话框被关闭,调用{MethodBase.GetCurrentMethod().Name}");
}
//当对话框被打开的时候触发这个方法,并且传递对话框参数进来
public void OnDialogOpened(IDialogParameters parameters)
{
Param = parameters.GetValue<string>("param");
}
#endregion
}
八、Module(模块)
1. prism项目在一个启动页当中划分好对应的区域。将不同的功能放到不同的module中,此时可以灵活的配置应用程序的功能,可以动态的加载应用程序模块,为指定的Region动态分配内容,即一个解决方案下有多个独立功能的module
2. 创建module
3. 如下图,主项目为PrismTest,又添加了两个独立的module:ModuleA、ModuleB
4. 在ModuleAModule.cs中注册对象,实现了IModule接口
public class ModuleAModule : IModule
{
public void OnInitialized(IContainerProvider containerProvider)
{
//绑定View与Region的映射关系 即名称为ModuleA的region区域将显示ViewA
var regionManager = containerProvider.Resolve<IRegionManager>();
regionManager.RegisterViewWithRegion("ModuleA",typeof(ViewA));
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
//也可以将module的view注册为导航 可以通过导航实现多个Module间的切换
containerRegistry.RegisterForNavigation(typeof(ViewA),"ViewA");
}
}
5. 添加模块,App.xaml.cs
//先添加对ModuleA项目的引用,然后重写添加模块函数。
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
base.ConfigureModuleCatalog(moduleCatalog);
//添加自定义模块 ModuleAModule: 这个是module模块实现了IModule的类
moduleCatalog.AddModule<ModuleAModule>();
}
参考:
[1] https://github.com/PrismLibrary/Prism
[2] WPF Prism(五)Navigation_目标:MVP-CSDN博客
[3] [Windows] Prism 8.0 入门(下):Prism.Wpf 和 Prism.Unity - 云+社区 - 腾讯云 (tencent.com)