WPF アプリケーションの終了条件(その1)の続きです。ShutdownMode プロパティが OnMainWindowClose または OnExplicitShutdown に設定されているときの動作はどうなるのでしょうか。

OnMainWindowClose

 ShutdownMode が OnMainWindowClose に設定されているときは、メインウィンドウを閉じたときにアプリケーションが終了します。これは Windows Forms アプリケーションの一般的な終了条件と同じです。

 Application クラスではメインウィンドウを管理する MainWindow プロパティを持っています。メインウィンドウが設定されていない状態で Window をインスタンス化すると自動的に MainWindow に設定されます。この MainWindow に設定されている Window を閉じた時に Shotdown メソッドが呼ばれます。

 アプリケーションの開始時にはメインウィンドウが設定されていないため、一番最初にインスタンス化した Window がメインウィンドウになります。また任意の Window を MainWindow に設定することもできます。MainWindow が閉じられると MainWindow は Nothing の状態になります。その時に新しい Window をインスタンス化するとそれが MainWindow に設定されます。

 この設定の時に注意することは、メインウィンドウにするつもりのない Window がメインウィンドウに設定されているかもしれないということです。次の例のように、ログインウィンドウを表示してからメインウィンドウを表示する時に、ログインウィンドウを閉じた時点でアプリケーションが終了してしまいます(サンプルコードの Application_Startup メソッドは Application.Startup イベントをハンドルしています)。

ログインウィンドウを閉じるとアプリケーションが終了してしまう例
Private Sub Application_Startup(ByVal sender As System.Object, ByVal e As System.Windows.StartupEventArgs)
    Me.ShutdownMode = System.Windows.ShutdownMode.OnMainWindowClose

    Dim login As New LoginWindow ' この時点で login が自動的に MainWindow に設定されてます。
    ' Application.Current.MainWindow = Nothing
    If login.ShowDialog() = False Then
        Application.Current.Shutdown()
    End If
    login.Close() ' login が MainWindow に設定されているためアプリケーションが終了します。

    Dim main As New TopWindow
    Application.Current.MainWindow = main ' main を MainWindow に設定しようとしても、手遅れです。
    main.Show()
End Sub

 これを回避するには、ログインウィンドウを MainWindow から解除してやることです。Application.Current.MainWindow = Nothing の部分のコメントを解除すると main が MainWindow として表示することができます。

OnExplicitShutdown

 ShutdownMode が OnExplicitShutdown に設定されているときは、明示的に Shutdown メソッドを呼ばない限りアプリケーションは終了しません。それだけです。(決して面倒くさくなってきたとかそんなんじゃありませんよ、それだけこの設定がシンプルだと言うことです)

まとめ

  • ShutdownMode が OnMainWindowClose に設定されているときは、メインウィンドウを閉じた時にアプリケーションが終了する。
  • 一番最初にインスタンス化した Window がメインウィンドウになる。
  • メインウィンドウは任意に変更することができる。
  • ShutdownMode が OnExplicitShutdown に設定されているときは、Shutdown メソッドを呼んだ時にアプリケーションが終了する。

 MainWindow には特定の Window 型のみが自動的に設定された方がいいような気がします。メインウィンドウというくらいですから、通常メインは一つだと思います。そうなっていればログインウィンドウの存在を気にすることなく、処理ができるようになったのではないでしょうか。また OnMainWindowClose が最も良く使いそうな設定なのに OnLastWindowClose が既定値になっているのに驚きです。WPF アプリケーションではどのようなシナリオを想定しているのでしょうか?