質問

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

役に立ちましたか?

解決

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top