.NET Core 3 WPF MVVM框架 Prism系列之对话框服务
本文将介绍如何在.net core3环境下使用mvvm框架prism的对话框服务,这也是prism系列的最后一篇完结文章,下面是prism系列文章的索引:
.net core 3 wpf mvvm框架 prism系列之文章索引
一.对话框服务
在prism中,通过一个idialogaware接口来实现对话框服务:
public interface idialogaware { bool canclosedialog(); void ondialogclosed(); void ondialogopened(idialogparameters parameters); string title { get; set; } event action<idialogresult> requestclose; }
- canclosedialog()函数是决定窗体是否关闭
- ondialogclosed()函数是窗体关闭时触发,触发条件取决于canclosedialog()函数
- ondialogopened()函数时窗体打开时触发,比窗体loaded事件早触发
- title为窗体的标题
- requestclose为关闭事件,可由此控制窗体的关闭
1.创建对话框的view和viewmodel
alertdialog.xaml:
<usercontrol x:class="prismmetrosample.shell.views.dialogs.alertdialog" 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:prismmetrosample.shell.views.dialogs" mc:ignorable="d" xmlns:prism="http://prismlibrary.com/" width="350" height="120" prism:viewmodellocator.autowireviewmodel="true"> <grid margin="5"> <grid.rowdefinitions> <rowdefinition /> <rowdefinition height="auto" /> </grid.rowdefinitions> <grid margin="0,0,0,10"> <grid.columndefinitions> <columndefinition width="70"/> <columndefinition/> </grid.columndefinitions> <image source="pack://application:,,,/prismmetrosample.infrastructure;component/assets/photos/alter.png" height="40" uselayoutrounding="true" renderoptions.bitmapscalingmode="highquality"/> <textblock grid.column="1" text="{binding message}" horizontalalignment="left" verticalalignment="center" grid.row="0" textwrapping="wrap" fontsize="15" fontfamily="open sans"/> </grid> <grid grid.row="1"> <grid.columndefinitions> <columndefinition/> <columndefinition/> </grid.columndefinitions> <button margin="5" foreground="white" fontsize="12" background="#5cb85c" command="{binding closedialogcommand}" commandparameter="true" content="yes" width="64" height="28" horizontalalignment="right" grid.row="1"/> <button grid.column="1" margin="5" foreground="white" fontsize="12" background="#d9534f" command="{binding closedialogcommand}" commandparameter="false" content="no" width="64" height="28" horizontalalignment="left" grid.row="1"/> </grid> </grid> </usercontrol>
alertdialogviewmodel.cs:
public class alertdialogviewmodel : bindablebase, idialogaware { private delegatecommand<string> _closedialogcommand; public delegatecommand<string> closedialogcommand => _closedialogcommand ?? (_closedialogcommand = new delegatecommand<string>(executeclosedialogcommand)); void executeclosedialogcommand(string parameter) { buttonresult result = buttonresult.none; if (parameter?.tolower() == "true") result = buttonresult.yes; else if (parameter?.tolower() == "false") result = buttonresult.no; raiserequestclose(new dialogresult(result)); } //触发窗体关闭事件 public virtual void raiserequestclose(idialogresult dialogresult) { requestclose?.invoke(dialogresult); } private string _message; public string message { get { return _message; } set { setproperty(ref _message, value); } } private string _title = "notification"; public string title { get { return _title; } set { setproperty(ref _title, value); } } public event action<idialogresult> requestclose; public bool canclosedialog() { return true; } public void ondialogclosed() { } public void ondialogopened(idialogparameters parameters) { message = parameters.getvalue<string>("message"); } }
2.注册对话框
app.cs:
protected override void registertypes(icontainerregistry containerregistry) { containerregistry.registerdialog<alertdialog, alertdialogviewmodel>(); }
还可以注册时起名字:
containerregistry.registerdialog<alertdialog, alertdialogviewmodel>(“alertdialog”);
3.使用对话框服务
createaccountviewmodel.cs(修改部分):
public createaccountviewmodel(iregionmanager regionmanager, idialogservice dialogservice) { _regionmanager = regionmanager; _dialogservice = dialogservice; } public void confirmnavigationrequest(navigationcontext navigationcontext, action<bool> continuationcallback) { if (!string.isnullorempty(registeredloginid) && this.isuserequest) { _dialogservice.showdialog("alertdialog", new dialogparameters($"message={"是否需要用当前注册的用户登录?"}"), r => { if (r.result == buttonresult.yes) navigationcontext.parameters.add("loginid", registeredloginid); }); } continuationcallback(true); }
效果如下:
我们是通过调用idialogservice接口的showdialog函数来调用,下面是该接口的定义:
public interface idialogservice : object { void show(string name, idialogparameters parameters, action<idialogresult> callback); void showdialog(string name, idialogparameters parameters, action<idialogresult> callback); }
我们可以发现show和showdialog函数都是一样形参,无非就是使用场景不一样
- name:所要调用对话框view的名字,当注册别名时,只能使用别名来调用
- parameters:idialogparameters接口类型参数,传入的提示消息,通常是$"message={xxxx}"格式,然后再viewmodel的ondialogopened函数通过idialogparameters接口的getvalue函数来获取
- callback:用于传入无返回值回调函数
二.自定义对话框窗体
我们在上述可以看到,对话框的窗体时一个wpf自带的窗体,但是当我们要用自己自定义窗体,例如,去掉window的icon,保留最大化,最小化和关闭,或者使用一些第三方的窗体控件,prism支持通过注册一个对话框窗体,然后通过再不同对话框的view指定其对话框窗体的style,则可以很灵活的实现不一样的对话框,下面让我们来看看如何操作:
1.注册自定义对话框窗体
新建一个窗体,dialogwindow.xaml:
<window x:class="prismmetrosample.shell.views.dialogs.dialogwindow" 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:prismmetrosample.shell.views.dialogs" mc:ignorable="d" xmlns:prism="http://prismlibrary.com/" > <grid> </grid> </window>
dialogwindow.xaml.cs:
public partial class dialogwindow : window, idialogwindow { public dialogwindow() { initializecomponent(); } protected override void onsourceinitialized(eventargs e) { windowhelp.removeicon(this);//使用win32函数去除window的icon部分 } public idialogresult result { get; set; } }
app.cs:
protected override void registertypes(icontainerregistry containerregistry) { containerregistry.registerdialogwindow<dialogwindow>();//注册自定义对话框窗体 }
2.自定义对话框窗体style
alertdialog.xaml:
<prism:dialog.windowstyle> <style targettype="window"> <setter property="prism:dialog.windowstartuplocation" value="centerscreen" /> <setter property="showintaskbar" value="false"/> <setter property="sizetocontent" value="widthandheight"/> </style> </prism:dialog.windowstyle>
效果如下:
如何我们要将窗体样式全部去掉,改动alertdialog.xaml:
<prism:dialog.windowstyle> <style targettype="window"> <setter property="prism:dialog.windowstartuplocation" value="centerscreen" /> <setter property="showintaskbar" value="false"/> <setter property="sizetocontent" value="widthandheight"/> <setter property="windowstyle" value="none"/> </style> </prism:dialog.windowstyle>
那么就变成了下面这样:
最终,我们的最后效果为这样:
三.小结
通过prism的对话框服务,我们可以很好的通过一个idialogservice接口来统一管理对话框的弹出逻辑,而且可以使用依赖注入的模式,如果换成之前要定义一些自定义的对话框,那么也要强依赖view部分,而且可以通过自定义不同对话框的窗体样式,达到一定的灵活性(例如最终效果演示,用了两个不同的对话框样式),至此, .net core3.x prism系列文章已经全部写完
四.源码
最后,附上整个demo的源代码:prismdemo源码
推荐阅读
-
.NET Core 3 WPF MVVM框架 Prism系列之模块化
-
.NET Core 3 WPF MVVM框架 Prism系列之区域管理器
-
.NET Core 3 WPF MVVM框架 Prism系列之事件聚合器
-
.NET Core 3 WPF MVVM框架 Prism系列之对话框服务
-
.NET Core 3 WPF MVVM框架 Prism系列之导航系统
-
.NET Core 3 WPF MVVM框架 Prism系列之区域管理器
-
.NET Core 3 WPF MVVM框架 Prism系列之模块化
-
.NET Core 3 WPF MVVM框架 Prism系列之事件聚合器
-
.NET Core 3 WPF MVVM框架 Prism系列之导航系统
-
.NET Core 3 WPF MVVM框架 Prism系列之对话框服务