【Prism系列】Prism子窗口实现
前言
上节介绍的事件聚合器其实就可以实现MVVM模式下的弹窗过程,不过Prism非常贴心的有封装了专门实现子窗口的全套逻辑。
IDialogAware
既然要打开子窗口,那我们需要准备内容,但是窗口本身是prism准备好的,我们需要的准备是窗口内容,所以这里我新建一个用户控件,最终这个用户控件会被安排在一个prism为我们准备好的窗口里。我们为这个用户控件(view), 准备一个ViewModel,注意这个ViewModel需要实现接口IDialogAware。
1 新建用户控件
新建一个用户控件,命名一个类名就叫 “MyDialog” 吧,记住这个名字后续注册时用到:
<UserControl x:Class="WpfTest.Control.MyDialog"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:WpfTest.Control"mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"><StackPanel><TextBlock Text="我是个子窗口" FontSize="30"/><Button Command="{Binding BtnCloseCommand}" Content="Close" Width="200"/></StackPanel>
</UserControl>
2 新建一个ViewModel
给 “MyDialog”配套一个 “MyDialogViewModel.cs” ,注意该类需要实现接口IDialogAware。
internal class MyDialogViewModel: BindableBase, IDialogAware{#region IDialogAware的接口实现// 窗口标题public string Title => "弹窗";// 关闭弹窗操作public event Action<IDialogResult> RequestClose;// 是否允许关闭弹窗public bool CanCloseDialog(){return true;}// 当窗口关闭的调用public void OnDialogClosed(){MessageBox.Show("窗口关闭了!");}// 当窗口打开的时候调public void OnDialogOpened(IDialogParameters parameters){MessageBox.Show($"窗口打开了!" + "\n" +$"{parameters.GetValue<MainWindowViewModel>("123")}" + "\n" +$"{parameters.GetValue<string>("456")}");}#endregionprivate string name = "bean";public string Name{get { return name; }set { SetProperty(ref name, value); }}private string key = "321mima";public string Key{get { return key; }set { SetProperty(ref key, value); }}public DelegateCommand BtnCloseCommand { get => new DelegateCommand(() =>{// 关闭当前窗口RequestClose?.Invoke(new DialogResult(ButtonResult.OK));});}}
3 窗口内容注册
将我们刚刚新建的用户控件,在App的回调函数RegisterTypes中通过RegisterDialog方法注册到Prism的容器中,确保后期容器知道打开什么内容。
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{// 注册一个Dialog的内容containerRegistry.RegisterDialog<MyDialog>();
}
准备工作差不多了,接下来就看看,如何打开这个窗口了。
4 确保MyDialog和MyDialogViewModel是关联上
我们可以通过Prism的默认匹配规则(Views => ViewModels)。
也可以通过手动进行匹配:
ViewModelLocationProvider.Register<MyDialog, MyDialogViewModel>();
如果没匹配,则会报错如下:告诉你Dialog的ViewModel没有实现接口IDialogAware
IDialogService
Prism框架在初始化的时候,就会向容器中注册17项内容,事件聚合器是其一,IDialogService就是其二。它规定了窗口的打开方式。我们之前准备好的窗口内容就由它打开。
1 注入IDialogService
由于IDialogService是prism框架预先注册好的,所以,我们直接在MainWindowViewModel注入(MainWindowViewModel,对应的是主窗口):
[Dependency]
public IDialogService dialogService { get; set; }
2 ShowDialog打开窗口
这里ShowDialog和之前的实现了IDialogAware接口的MyDialogViewModel息息相关。
public DelegateCommand BtnCommand { get; }[Dependency]
public IDialogService dialogService { get; set; }public Prism子窗口实现ViewModel()
{BtnCommand = new DelegateCommand(() => {DialogParameters dialogParameters = new DialogParameters();dialogParameters.Add("123", this);dialogParameters.Add("456", "asdf");dialogService?.ShowDialog("MyDialog", dialogParameters, DoDialogResult);});
}private void DoDialogResult(IDialogResult dialogResult)
{// 委托 被动执行 被子窗口执行// dialogResult 第一方面可以拿到任意参数 第二方面 可判断关闭状态MessageBox.Show("返回值:" + dialogResult.Result.ToString());
}
ShowDialog的时候,我们传入的三个参数。
第一个参数,“MyDialog” ,这个就是我们之前新建的用户控件的类名称,也是我们往容器注册过的类:
containerRegistry.RegisterDialog<MyDialog>();
这里传入字符串“MyDialog” ,Prism就找到之前通过RegisterDialog注册的MyDialog。
第二个参数,dialogParameters 打开窗口可以传入的参数,以键值对的方式,键必须是字符串,值可以是任何内容。
DialogParameters dialogParameters = new DialogParameters();
dialogParameters.Add("123", this);
dialogParameters.Add("456", "asdf");
之前和MyDialog关联实现了IDialogAware的的MyDialogViewModel,就有个实现了一个OnDialogOpened,ShowDialog传入的参数就会在窗口打开时,传入这个函数。
第三个参数,DoDialogResult,是一个回调函数,当窗口关闭之后被调用
private void DoDialogResult(IDialogResult dialogResult)
{// 委托 被动执行 被子窗口执行// dialogResult 第一方面可以拿到任意参数 第二方面 可判断关闭状态MessageBox.Show("返回参数:" + dialogResult.Parameters.ToString());MessageBox.Show("返回值:" + dialogResult.Result.ToString());
}
这里函数里还有个参数,是对话框返回的结果,如果直接点击关闭按钮关闭的窗口,dialogResult参数里面就没啥内容。
那如何,在关闭之后得到对话框的一些信息呢?
这又要看:实现了IDialogAware的的MyDialogViewModel里面的事件:
public event Action<IDialogResult> RequestClose;
通过触发该事件,就可以关闭窗口并传入参数:
public DelegateCommand BtnCloseCommand { get => new DelegateCommand(() =>
{// 关闭当前窗口//RequestClose?.Invoke(new DialogResult(ButtonResult.OK));DialogParameters dialogParameters = new DialogParameters();dialogParameters.Add("123", 123);dialogParameters.Add("456", "456");RequestClose?.Invoke(new DialogResult(ButtonResult.Retry, dialogParameters));
});
}
这里有个地方,需注意:RequestClose?.Invoke 不能写到 接口方法 OnDialogClosed() 里面。
程序执行到这里时,你会发现 RequestClose 已经为 NULL 了, RequestClose 是Prsim框架赋值的
当事件触发时,窗口会关闭,此时DoDialogResult就会被框架调用,此时dialogResult得到了,触发事件时传入的参数ButtonResult.Retry,以及相应的dialogParameters 。
总结
为了实现MvvM整个实现过程,有亿点绕,这里从头梳理一遍。
1 需要建立一个用户控件(MyDialog)充当窗口内容,Prism框架提供默认窗口包含此用户控件。
2 需要为用户控件,配置一个ViewModel(MyDialogViewModel),此 ViewModel必须实现接口IDialogAware
3 MyDialog与MyDialogViewModel需要关联起来
4 需要通过RegisterDialog注册MyDialog
5 在主窗口中注入IDialogService对象,dialogService 。主窗口中dialogService调用ShowDialog
打开子窗口,通过ShowDialog参数以及实现了IDialogAware的MyDialogViewModel实现窗口调用前的参数输入,以及窗口关闭后的结果输出。
内容扩充
窗口样式设计
方式一:
因为,这里我们使用的是用户控件,而窗口其实是Prism提供的,那如何设置窗口的样式呢?
我们,可以添加如下代码,进行窗口设置。
<prism:Dialog.WindowStyle><Style TargetType="Window"><Setter Property="Width" Value="500"/><Setter Property="Height" Value="400"/><Setter Property="WindowStyle" Value="None"/><Setter Property="AllowsTransparency" Value="True"/><Setter Property="WindowChrome.WindowChrome"><Setter.Value><WindowChrome GlassFrameThickness="-1"/></Setter.Value></Setter></Style>
</prism:Dialog.WindowStyle>
方式二:
不使用prism提供的窗口,而是自己窗口:
首先我们新建一个窗口DialogWindowBase,然后让该窗口实现接口IDialogWindow:
public partial class DialogWindowBase : Window, IDialogWindow{public IDialogResult Result{get; set;}public DialogWindowBase(){InitializeComponent();}}
最后在APP类中注册,该窗口:
containerRegistry.RegisterDialogWindow<DialogWindowBase>();
那么prism就会使用这个窗口而不是默认的,那么我们设置这个窗口就OK了。
2022年12月7日 更新内容:
RequestClose?.Invoke 不能写到 接口方法 OnDialogClosed() 里面。
【Prism系列】Prism子窗口实现相关推荐
- 【Prism系列】Module实现程序的插件化
前言 首先区分Module和model这两个单词.model是之前MVVM提到很多的模型部分.而今天讲的是Module:模块/单元.Module有助于我们将程序分成一个个模块进行管理.借助Module ...
- .NET Core 3 WPF MVVM框架 Prism系列之事件聚合器
本文将介绍如何在.NET Core3环境下使用MVVM框架Prism的使用事件聚合器实现模块间的通信 一.事件聚合器 在上一篇 .NET Core 3 WPF MVVM框架 Prism系列之模块化 ...
- c#事件的发布-订阅模型_NET Core 3 WPF MVVM框架 Prism系列之事件聚合器
本文将介绍如何在.NET Core3环境下使用MVVM框架Prism的使用事件聚合器实现模块间的通信 一.事件聚合器# 在上一篇 .NET Core 3 WPF MVVM框架 Prism系列之模块化 ...
- 【Prism系列】Prism中的命令
前言 在<[Prism系列] Prism实现依赖注入_code bean的博客-CSDN博客>中我们讲到了prism的搭建过程,以及如何容器的使用以及自动注入的过程. 在<[wpf] ...
- FineUI小技巧(5)向子窗口传值,向父窗口传值
前言 FineUI中经常会用到启用IFrame的Window控件,这样有助于从物理上进行代码解耦和.IFrame的引入就会涉及传值问题,如何在父窗口和子窗口之间相互传值呢? 向子窗口传值 向子窗口传值 ...
- 代码赏析:子窗口对于键盘和鼠标的响应
一.引言 首先声明,代码并不是我写的:其次,代码是我在小甲鱼的<Win32 SDK程序设计>系列教程的第41讲中看到的.因为本人一方面在学习这个教程,一方面也对于优美的代码有着自己的独特的 ...
- Python 的Tkinter包系列之一:窗口初步
Python 的Tkinter包系列之一:窗口初步 图形用户界面(GUI.Graphical User Interface)是基于图形的界面,windows就是一个图形用户界面的操作系统,而DOS是基 ...
- python label textvariable_在子窗口中为标签的textvariable赋值失败时,有关,给,Label,问题...
写了个母子窗体程序,当主窗口打开子窗口后,通过set textvariable 的发发对Label标题赋值失败,如果将子窗体程序单独运行,则正常.请教各位大神如果处理,多谢! from tkinter ...
- 请问,关闭子窗口提示错误,大家遇到这样的问题吗?
请问,关闭子窗口提示错误,大家遇到这样的问题吗? Delphi / Windows SDK/API http://www.delphi2007.net/DelphiBase/html/delphi_2 ...
最新文章
- 像素钱包:一个可以把比特现金藏在图片里的APP
- eclipse里面M2_REPO引用(Maven2安装总结)
- Prima Cartoonizer中文版
- 简单形象又有趣地说说强大的神经网络
- 广东移动数据中心攻关“液/气双通道散热技术”
- linux——Shell脚本说明、创建、执行、调试
- Spark中Data skew(数据倾斜)Java+Python+Scala三种接口完整代码
- 程序设计入门-C语言基础知识-翁恺-第六周:数组-详细笔记(六)
- python中的运算符_Python 中的神秘运算符
- 人类一败涂地电脑版_《漫威复仇者联盟》帧数对比丨PS4《人类一败涂地》新地图上线...
- java如何获取本机IP
- 小波包分解、重构 matlab代码
- 学校机房计算机安全使用制度,学校机房安全管理制度
- 国内多少所高校开始博士生采用申请招生的方法了?
- 方差为什么用平方不用绝对值,为什么要对差值求平方而不是取标准偏差的绝对值?...
- 机器人理论简介—— 台湾交通大学机器人学公开课(一)
- win10无限重启_安装 Win10+Ubuntu双系统,让迷你掌上电脑更具生产力
- C# 读取outlook 本地签名
- 安装openKylin 开源操作系统 (ubuntukylin-22.04-pro-amd64.isowindows版)
- Windows桌面任务栏上面无线网显示不见了如何解决