2016-03-21 135 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中設置。 –