【问题标题】:Callback from Dialog window to Main window从对话框窗口回调到主窗口
【发布时间】:2023-11-19 06:35:01
【问题描述】:

我正在开发一个 WPF MVVM 应用程序,它使用 MVVMLightToolkit 作为第三方助手。我的场景如下:

我有一个主窗口,在关闭主窗口时,我必须显示一个新的对话框窗口(保存更改对话框窗口)来确认用户是否必须保存他在应用程序中提出了一个状态文件或不是。如何在 MVVM 中处理这种情况?通常为了显示一个新窗口,我使用 MVVMLight Messenger 类。在这种情况下,我从 Main Window 打开 Save Changes Dialog window 后面的代码。我需要根据从“保存更改”对话框窗口中选择的用户选项(SAVE、SAVE/EXIT、CANCEL)回调主视图模型,并基于此我必须检查是否必须是否关闭主窗口。处理这种情况的最佳 MVVM 方法是什么?

【问题讨论】:

    标签: .net wpf mvvm callback mvvm-light


    【解决方案1】:

    只需将消息从/传递到 ViewModel。

    查看

    private void Window_Closing(object sender, CancelEventArgs e)
    {
        Messenger.Default.Send(new WindowRequestsClosingMessage(
            this, 
            null,
            result => 
            { 
                if (!result)
                    e.Cancel = true;
            });
    }
    

    视图模型

    Messenger.Default.Register<WindowRequestsClosingMessage>(
        this,
        msg => 
        {
    
            // Your logic before close
    
            if (CanClose)
                msg.Execute(true);
            else
                msg.Execute(false);
        });
    

    留言

    public class WindowRequestsClosingMessage: NotificationMessageAction<bool>
    {
        public WindowRequestsClosingMessage(string notification, Action<bool> callback)
            : base(notification, callback)
        {
        }
    
        public WindowRequestsClosingMessage(object sender, string notification, Action<bool> callback)
            : base(sender, notification, callback)
        {
        }
    
        public WindowRequestsClosingMessage(object sender, object target, string notification, Action<bool> callback)
            : base(sender, target, notification, callback)
        {
        }
    }
    

    MVVM Light 的 NotificationMessageAction 允许您传递消息并获得 TResult 类型的结果。要将 TResult 传递回请求者,请像示例一样调用 Execute()

    【讨论】:

      【解决方案2】:

      你为什么不在你的闭幕式中做如下的事情:

          private void Window_Closing(object sender, CancelEventArgs e)
          {
              SaveDialog sd = new SaveDialog();
              if (sd.ShowDialog() == false)
              {
                  e.Cancel = true;
              }
          }
      

      【讨论】:

      • SaveDialog.ShowDialog() 返回一个可为空的布尔值。我的应用程序是 WPF 应用程序而不是 Windows。
      • 所以把SaveDialogResults.Cancel改成true或者false或者null,随便你^^
      • 感谢您的回复。实际上 Window_Closing 命令是使用 RelayCommand 从 ViewModel 处理的。从该命令处理程序中,使用 Messenger(MVVMLight) 我从后面的主窗口代码中显示 SaveChanges 对话框窗口。我需要回调主视图模型命令处理程序并从保存对话框窗口传递选定的选项。希望您现在了解我的情况。
      • 好的。我对 MVVMLight 不熟悉,但你不能只用 Messenger 向你的 ViewModel 发送一条消息,比如Messenger.Send&lt;bool?, ViewModel&gt;(SaveDialog.ShowDialog()); 并通过Messenger.Register&lt;bool?&gt;(this, delegate(bool? result) { });注册它
      • 我需要回调主窗口关闭命令处理程序方法,以便保存状态。如果我按照您的建议从视图向视图模型发送消息,我没有收到对该方法的回调。