【问题标题】:WPF MVVM cancel Window.Closing eventWPF MVVM 取消 Window.Closing 事件
【发布时间】:2014-05-12 16:00:59
【问题描述】:

在 WPF 应用程序和 MVVMLight Toolkit 中,我想看看你的意见,如果我需要取消 Window Close 事件,最好的实现方式是什么。 在 Window.Closing 事件中,我可以设置 e.Cancel = true,以防止关闭表单。在 ViewModel 上下文中确定是否允许关闭或应该阻止关闭。

如果我定义一个应用程序变量,我可以在后面的视图代码中的普通事件处理程序中查询它,一个解决方案可能是?

谢谢

【问题讨论】:

  • 在普通的 MVVM 中,它带有附加属性是直截了当的。不知道它是如何与 MVVMLight 一起工作的......

标签: wpf mvvm-light


【解决方案1】:

使用 MVVM Light,您将获得 EventToCommand

因此您可以在 xaml 中将关闭事件连接到 VM。

<Window ...
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:command="http://www.galasoft.ch/mvvmlight">
<i:Interaction.Triggers>
  <i:EventTrigger EventName="Closing">
    <command:EventToCommand Command="{Binding ClosingCommand}"
                            PassEventArgsToCommand="True" />
  </i:EventTrigger>
</i:Interaction.Triggers>

在虚拟机中:

public RelayCommand<CancelEventArgs> ClosingCommand { get; private set; }

ctor() {
  ClosingCommand = new RelayCommand<CancelEventArgs>(args => args.Cancel = true);
}

如果您不想将CancelEventArgs 传递给虚拟机

您始终可以对Behavior 采取类似的方法,只需使用来自VM 的简单bool(将此布尔值绑定到行为)来指示应取消关闭事件。

更新:

Download Link for following example

要使用Behavior 执行此操作,您可以使用Behavior,例如:

internal class CancelCloseWindowBehavior : Behavior<Window> {
  public static readonly DependencyProperty CancelCloseProperty =
    DependencyProperty.Register("CancelClose", typeof(bool),
      typeof(CancelCloseWindowBehavior), new FrameworkPropertyMetadata(false));

  public bool CancelClose {
    get { return (bool) GetValue(CancelCloseProperty); }
    set { SetValue(CancelCloseProperty, value); }
  }

  protected override void OnAttached() {
    AssociatedObject.Closing += (sender, args) => args.Cancel = CancelClose;
  }
}

现在在 xaml 中:

<i:Interaction.Behaviors>
  <local:CancelCloseWindowBehavior CancelClose="{Binding CancelClose}" />
</i:Interaction.Behaviors>

其中CancelClose 是来自VM 的布尔属性,它指示是否应该取消Closing 事件。在附加的示例中,我有一个 Button 来从 VM 切换此布尔值,这应该可以让您测试 Behavior

【讨论】:

  • 是的,这可能是一个解决方案,但我想保留 MVVM 的优势,尽可能多地分离视图和模型。如何用 Behavior 处理这个问题?如果我使用 bool 值是否可以取消窗口关闭事件?
  • @pillesoft 检查答案末尾的更新以获取使用Behavior 的示例。还有一个下载链接,应该为您提供要测试的项目中的示例。要记住的一件事是,MVVM 相对于 MVC 等模式的主要优势是允许对 VM 代码进行单元测试。因此,如果您可以在 VM 中很好地对您的逻辑进行单元测试(在这种情况下您可以使用单元测试项目),我个人不会立即将这种方法标记为错误。
  • 我可以像这样使用 MVVM 轻量级方法沿 eventArgs 传递参数吗?
  • Behavior 对我有用,但是如果你有 InvokeCommandAction 和 Closing 事件的行为,那么首先调用 Behavior。
【解决方案2】:

您可以使用Messages 来控制它,例如:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        Messenger.Default.Register<CloseApplicationMessage>(this, m => Close());
        Loaded += MainWindowLoaded;
        Closing += MainWindowClosing;
    }

    private void MainWindowClosing(object sender, CancelEventArgs e)
    {
        //Ask for saving
        var closingMessage = new ClosingApplicationMessage();
        Messenger.Default.Send(closingMessage);
        if (closingMessage.Cancel)
            e.Cancel = true;
    }
...

mvvm 消息:

public class ClosingApplicationMessage
{
    public bool Cancel { get; set; }
}

这样,在您正在收听ClosingApplicationMessage的任何地方,您都可以控制应用程序何时关闭,并且可以取消它。 希望这会有所帮助...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-20
    • 1970-01-01
    • 2011-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-04
    相关资源
    最近更新 更多