欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

.NET Core 3 WPF MVVM框架 Prism系列之对话框服务

程序员文章站 2022-03-08 14:13:57
本文将介绍如何在.NET Core3环境下使用MVVM框架Prism的对话框服务,这也是prism系列的最后一篇完结文章,下面是Prism系列文章的索引: ".NET Core 3 WPF MVVM框架 Prism系列之文章索引" 一.对话框服务 在Prism中,通过一个 IDialogAware ......

 本文将介绍如何在.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);

 }

效果如下:

.NET Core 3 WPF MVVM框架 Prism系列之对话框服务

我们是通过调用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>

效果如下:

.NET Core 3 WPF MVVM框架 Prism系列之对话框服务

如何我们要将窗体样式全部去掉,改动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>

那么就变成了下面这样:

.NET Core 3 WPF MVVM框架 Prism系列之对话框服务

最终,我们的最后效果为这样:

.NET Core 3 WPF MVVM框架 Prism系列之对话框服务

三.小结

 通过prism的对话框服务,我们可以很好的通过一个idialogservice接口来统一管理对话框的弹出逻辑,而且可以使用依赖注入的模式,如果换成之前要定义一些自定义的对话框,那么也要强依赖view部分,而且可以通过自定义不同对话框的窗体样式,达到一定的灵活性(例如最终效果演示,用了两个不同的对话框样式),至此, .net core3.x prism系列文章已经全部写完

四.源码

 最后,附上整个demo的源代码:prismdemo源码