次の方法で共有


WPF WindowがCloseされたことの検出方法

質問

2017年9月28日木曜日 3:38

Visual Studio 2010でWPFアプリケーションを開発しています。
Window1からWindow2の表示・非表示をVisibilityプロパティーでコントロールしていますが、ユーザーが「閉じる」ボタンを押すとVisibilityプロパティーの操作時に例外が発生します。
例外の内容:
System.InvalidOperationException はハンドルされませんでした。
  Message=Window が閉じた後で、Visibility の設定や、Show、ShowDialog、および WindowInteropHelper.EnsureHandle の呼び出しを行うことはできません。

Windowが閉じられていることを検出するプロパティーがあるのならば、教えていただきたいです。よろしくお願い致します。

■■■<Window1:Main>

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="178" Width="432">
    <Grid>
        <Button Content="Button" Height="27" HorizontalAlignment="Left" Margin="50,30,0,0" Name="Button1" VerticalAlignment="Top" Width="102" />
    </Grid>
</Window>

Class MainWindow
    Private Property W2 As window2
    Private Property b1 As Boolean

    Private Sub Button1_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click

        If b1 = True Then
            W2.Visibility = Windows.Visibility.Visible
        Else
            W2.Visibility = Windows.Visibility.Hidden
        End If

        b1 = Not (b1)

    End Sub

    Private Sub window1_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded
        W2 = New window2
        W2.Show()
    End Sub
End Class

■■■<Window2>

<Window x:Class="window2"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="window2" Height="126" Width="170">
    <Grid></Grid>
</Window>

(コードビハインドは無し)

すべての返信 (4)

2017年9月28日木曜日 5:38 ✅回答済み

Windowが閉じられていることを検出するプロパティーがあるのならば、教えていただきたいです。

子ウィンドウが閉じられているかどうかを検出するというより、ユーザーが子ウィンドウを閉じようとしたときに子ウィンドウを閉じるのではなく子ウィンドウを非表示にするようにするとよいかもしれませんね。

Imports System.Windows.Interop

Public Class window2
    Private Sub Window1_SourceInitialized(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.SourceInitialized
        Dim wih As New WindowInteropHelper(Me)
        Dim hs As HwndSource = HwndSource.FromHwnd(wih.Handle)
        hs.AddHook(AddressOf WndProc)
    End Sub

    Private Function WndProc(ByVal hwnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr, ByRef handled As Boolean) As IntPtr
        Const WM_SYSCOMMAND As Integer = &H112
        Const SC_CLOSE As Long = &HF060L
        Select Case msg
            Case WM_SYSCOMMAND
                If (wParam.ToInt64() And &HFFF0L) = SC_CLOSE Then
                    ' ユーザーがウィンドウを閉じようとしたとき、ウィンドウを閉じるのをやめ非表示にする
                    Visibility = Visibility.Hidden
                    handled = True
                End If
                Exit Select
        End Select
        Return IntPtr.Zero
    End Function
End Class
Class MainWindow
    Private Property W2 As window2

    Private Sub window1_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded
        W2 = New window2
        W2.Show()
    End Sub

    Private Sub button_Click(sender As Object, e As RoutedEventArgs) Handles button.Click
        If W2.Visibility = Visibility.Visible Then
            W2.Visibility = Visibility.Hidden
        Else
            W2.Visibility = Visibility.Visible
        End If
    End Sub

    Private Sub Window_Closed(sender As Object, e As EventArgs)
        W2.Close()
    End Sub
End Class

2017年9月28日木曜日 3:55

Window の IsLoaded でウィンドウが閉じているか確認できるようです。

If W2.IsLoaded Then
    If b1 = True Then
        W2.Visibility = Visibility.Visible
    Else
        W2.Visibility = Visibility.Hidden
    End If
    b1 = Not (b1)
End If

参考サイト: https://stackoverflow.com/questions/381973/how-do-you-tell-if-a-wpf-window-is-closed


2017年9月28日木曜日 5:12

kenjinoteさん、回答ありがとうございます。

IsLoadedでウィンドウが閉じているかを読み取ることができるのは分かったのですが、一度でもcloseされてしまうと、showメソッドさえも実行できない(同じ例外が発生してしまう)ので、お答えいただいたロジックでは、処理が継続できなくなってしまいます。
「Window が閉じた後で、Visibility の設定や、Show、ShowDialog、およびWindowInteropHelper.EnsureHandle の呼び出しを行うことはできません。」

親Windowからは、子Windowの表示・非表示をコントロールできれば、それ以上のことは求めませんので、何か良い解決方法はないでしょうか。
(W2 As window2のインスタンスを削除してリコンストラクトするというのも、スマートでないのでやりたくありません。)

よろしくお願い致します。


2017年9月28日木曜日 6:27

どうもお手数をお掛けしました。
今まで、この解決方法がどうしても分からず、グシャグシャなプログラムを記述して表面上しのいでいましたが、これまでに作った子Window関連の箇所は、御教授いただいた方法で書き直す作業に入ります。御回答誠にありがとうございました。