2017-09-13 3 views
1

私はユーザーが必要に応じてより多くのウィンドウを動的に作成できるアプリケーションを作成しています。アプリケーションは常にのMainWindowの1つのインスタンスを持ち、0以上のAuxWindowインスタンスを持ちます。WPF:Window_Closing()をトリガーせずにプログラムを使用してウィンドウを閉じる

さらに多くのAuxWindowインスタンスを追加すると問題なく動作します。しかし、私はプログラム的に(つまり、ユーザーが補助的なウィンドウの数を減らしたい場合)問題をもう一度閉じることができます。 AuxWindow VMからAuxWindow.Close()を呼び出すと、Window_Closing()メソッドがトリガされ、ユーザに確認を求めるようになります。

したがって、ウィンドウを閉じるユーザーとアプリケーションを実行するアプリケーションを区別するにはどうすればよいですか?ユーザーがウィンドウを閉じると、確認を求めてからアプリケーション全体を終了します。しかし、アプリケーションがウィンドウを閉じている場合、私はそれを閉じたいだけです。

はここAuxWindowでWINDOW_CLOSING()メソッドです:

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { 
    _logger.Info("Exit application initiated - closing window"); 
    var result = _auxWindowVM.Controller.ExitApplication(this); 
    if (result == false) { 
     _logger.Info("Closing application confirmed"); 
     e.Cancel = false; 
    } 
    else { 
     _logger.Info("Closing application canceled"); 
     e.Cancel = true; 
    } 
} 

そしてここExitApplication方法は、メインウィンドウとすべてのAuxWindowインスタンスの両方から呼び出されています:私はAuxWindowするためのインタフェースを導入する

public bool ExitApplication(Window initWindow) { 
    if (_exitConfirmed == false) { 
     if (System.Windows.MessageBox.Show("Are you sure you want to exit?", "", System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Question, System.Windows.MessageBoxResult.No) == System.Windows.MessageBoxResult.Yes) { 
      MainWindowVM.CurrentDateTimeUpdateTimer.Stop(); 
      SerialPortHandler.SerialPortCts.Cancel(); 
      ArgusMk2CommProtocol.QueueConsumerCts.Cancel(); 
      PollingHandler.PollingTimer.Stop(); 
      _exitConfirmed = true; 
      Application.Current.Shutdown(); 
      return false; 
     } 
     else { 
      return true; 
     } 
    } 
    else { 
     return false; 
    } 
} 

答えて

2

これを処理するためのものです。 (なぜインタフェースビューとビューモデルの間には緊密な結合はありませんだけ確保するために、MVVMとSOLIDを参照してください。)

interface ICloseableView 
{ 
    void Close(bool confirmClose); 
} 

は、その後、私は私の意見では、このインタフェースを実装します:

class AuxWindow : Window, ICloseableView 
{ 
    private bool confirmClose = true; 

    public void Close(bool confirmClose) 
    { 
     try 
     { 
      this.confirmClose = confirmClose; 
      Close(); 
     } 
     finally 
     { 
      this.confirmClose = true; 
     } 
    } 

    private void Window_Closing(object sender, CancelEventArgs e) 
    { 
     if (!this.confirmClose) 
     { 
      e.Cancel = false; 
      return; 
     } 

     // Your code here... 
    } 

} 

最後に、AuxWindowのビューモデルでは、このメソッドをインターフェイス参照で取得します。ビューモデルは、具体的なビューの実装を意識するべきではありませんので、AuxWindow参照して、ビューモデルを提供するために、悪い習慣だが、それはそれをIClosableView参照を与えるために完全にOKです:覚えてい

これを使用して
class AuxWindowViewModel : INotifyPropertyChanged 
{ 
    private readonly IClosableView view; 

    // E.g. use a dependency injection via constructor 
    public AuxWindowViewModel(IClosableView view) 
    { 
     this.view = view; 
    } 

    void CloseViewWithoutConfirmation() 
    { 
     this.view.Close(false); 
    } 
} 

GUIまたはキーボードショートカットを使用してAuxWindowを「通常の」方法で閉じると、いつでも確認ダイアログが表示されます。ビューモデルからビューを閉じると、そのダイアログは表示されません。

+0

オペレータが確認する必要があるかどうかを確認するローカルブール値についての素晴らしいアイデア。しかし、どのように私は(それは間違っているのですか?))それを参照することなく、それを行う "正しい"方法であることを教えてきたVMからビューをインスタンス化することはできますか?現時点では、VMコンストラクタでViewをインスタンス化し、VMをViewコンストラクタのView DataContextとして設定するときに、パラメータとしてVMを渡しています。間違いなく? – Oystein

+1

一般的に、ビューモデルはビューについて気にする必要はありません。これがMVVMのパラダイムの中心的な原則です。トピックはかなり複雑です。あなたはそれについてもっと読むことができます。 [ここに](https://softwareengineering.stackexchange.com/questions/330842/in-mvvm-should-viewmodel-or-view-be-responsible-for-creating-new-views)、ここでいくつかの研究を行う、それについて別の質問をするだけです。 – dymanoid

+0

情報ありがとうございます。 – Oystein

関連する問題