Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF MVVM cancel Window.Closing event

Tags:

wpf

mvvm-light

In WPF application together with MVVMLight Toolkit, I would like to see your opinion, what is the best way to implement if I need to Cancel the Window Close event. In Window.Closing event I can set the e.Cancel = true, which prevents closing the form. To identify if the Close is allowed, or should be prevented is in the ViewModel context.

One solution could be if I define an Application variable, and I can query this in the normal event handler in view code behind?

thanks

like image 525
pillesoft Avatar asked May 12 '14 16:05

pillesoft


1 Answers

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

like image 116
Viv Avatar answered Nov 09 '22 22:11

Viv