WPF MVVM cancel Window.Closing event

依然范特西╮ 提交于 2019-12-04 05:44:32

With MVVM Light you got EventToCommand:

So you could in xaml wire up the closing event to the 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>

and in the VM:

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

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

If you do not want to pass CancelEventArgs to the VM:

You could always take the similar approach with a Behavior and just use a simple bool from the VM(bind this bool to the Behavior) to indicate the closing event should be cancelled.

Update:

Download Link for following example

To do this with a Behavior you could just have a Behavior such as:

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;
  }
}

Now in xaml:

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

Where CancelClose is a bool property from the VM which indicates if the Closing event should be cancelled or not. In the attached example I have a Button to toggle this bool from the VM that should let you test the Behavior

You could to control this using Messages, for instance:

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;
    }
...

The mvvm message:

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

In this way, in any place you are listening to the ClosingApplicationMessage, you can control when the application is going to close, and may to cancel it. Hope this helps...

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!