Question

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

Was it helpful?

Solution

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

OTHER TIPS

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top