2016-03-21 10 views
4

キャンセルボタン(または右上隅のX、またはEsc)をクリックした後、特定のフォームからの終了をキャンセルするにはどうすればよいですか?MVVM WPFアプリケーションでウィンドウ終了をキャンセルする方法

WPF:

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

のViewModel:

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ボタン(右上)を管理することはできません。キャンセルボタンと混同していたようですが、XボタンまたはEscをクリックするとExecuteメソッドが実行されるためです。

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イベントのビューを購読し、CancelEventArgs.Cancelをtrueに設定してからMessageBoxと表示します。

ここ

は例です:背後

<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 evenに割り当てます。私がEDIT2の後に述べたように。しかし、この場合、私はどのように閉じられたのかを区別することはできません。私は、ICommandで設定する追加のフラグを追加することなく、意味します。 –

関連する問題