2016-03-21 106 views
4

如何在取消按钮(或右上角的X或Esc)被点击后取消从特定窗体退出?如何在MVVM WPF应用程序中取消窗口关闭

WPF:

<Window 
    ... 
    x:Class="MyApp.MyView" 
    ... 
/> 
    <Button Content="Cancel" Command="{Binding CancelCommand}" IsCancel="True"/> 
</Window> 

视图模型:

public class MyViewModel : Screen { 
    private CancelCommand cancelCommand; 
    public CancelCommand CancelCommand { 
    get { return cancelCommand; } 
    } 
    public MyViewModel() { 
    cancelCommand = new CancelCommand(this); 
    } 
} 

public class CancelCommand : ICommand { 

    public CancelCommand(MyViewModel viewModel) { 
    this.viewModel = viewModel; 
    } 

    public override void Execute(object parameter) { 
    if (true) { // here is a real condition 
     MessageBoxResult messageBoxResult = System.Windows.MessageBox.Show(
     "Really close?", "Warning", 
     System.Windows.MessageBoxButton.YesNo); 
     if (messageBoxResult == MessageBoxResult.No) { return; } 
    } 
    viewModel.TryClose(false); 
    } 

    public override bool CanExecute(object parameter) { 
    return true; 
    } 
} 

当前代码不起作用。如果在弹出对话框中选择“否”,我希望用户保持当前的形式。 此外,覆盖CanExecute并没有帮助。它只是禁用按钮。我想让用户点击按钮,但然后通知他/她,数据将会丢失。 也许我应该在按钮上分配一个事件监听器?

编辑:

我管理显示弹出取消按钮。但我仍然无法管理Esc或X按钮(右上角)。看起来我很迷惑取消按钮,因为Execute方法是当我点击X按钮或Esc时执行的。

EDIT2:

我改变了问题。这是'如何取消取消按钮'。但是,这不是我所期待的。我需要取消Esc或X按钮。 在 'MyViewModel' 我补充一下:

 protected override void OnViewAttached(object view, object context) { 
      base.OnViewAttached(view, context); 
      (view as MyView).Closing += MyViewModel_Closing; 
     } 

     void MyViewModel_Closing(object sender, System.ComponentModel.CancelEventArgs e) { 
      if (true) { 
       MessageBoxResult messageBoxResult = System.Windows.MessageBox.Show(
        "Really close?", "Warning", 
        System.Windows.MessageBoxButton.YesNo); 
       if (messageBoxResult == MessageBoxResult.No) { 
        e.Cancel = true; 
       } 
      } 
     } 

这解决了我的问题。但是,我需要ICommand才能理解,单击了哪个按钮,保存或取消。有没有办法消除事件的使用?

+3

贵'viewModel.TryClose(假)'功能,将事件发送到您的视图,关闭对话框?如果是这样,你可以从xaml代码中删除'IsCancel =“true”'。该部分导致表单关闭。 –

+0

@ qqww2如果我删除IsCancel =“true”,那么如果我单击Esc它不会关闭窗口。我希望窗口在Esc上关闭。 –

+1

注册一个'KeyBinding'到你的命令。 [Here](http://stackoverflow.com/questions/19697106/create-key-binding-in-wpf)就是一个例子。 –

回答

4

您正在尝试在ViewModel类中执行View的工作。让你的View类来处理结束请求,以及它是否应该被取消。

要取消关闭窗口,您可以订阅Closing事件并在显示MessageBox后将CancelEventArgs.Cancel设置为true。

下面是一个例子:

<Window 
    ... 
    x:Class="MyApp.MyView" 
    Closing="OnClosing" 
    ... 
/> 
</Window> 

后面的代码:

private void OnClosing(object sender, CancelEventArgs e) 
{ 
    MessageBoxResult result = MessageBox.Show("Really close?", "Warning", MessageBoxButton.YesNo); 
    if (result != MessageBoxResult.Yes) 
    { 
     e.Cancel = true; 
    } 

    bool shouldClose = ((MyViewModel) DataContext).TryClose(false); 
    if(!shouldClose) 
    { 
     e.Cancel = true; 
    } 
} 
+0

这里的问题是View不知道它是否应该关闭。我看不到我如何访问ViewModel数据。 –

+0

好的。你能否详细解释什么是关闭窗口的算法? –

+0

我将ViewModel中的处理程序分配给了OnClosing。就像我在EDIT2之后所说的那样。但是,在这种情况下,我无法区分如何关闭。我的意思是,没有添加额外的标志,我将在ICommand中设置。 –