如何判断WPF窗口是否关闭?

时间:2022-08-19 21:38:33

I'm working on an application that displays some child windows which can either be closed by the user or are automatically closed. While debugging some exceptions that were being thrown, I discovered I was trying to call methods like Hide() on a window that had already been closed; this particular branch of code was common to both cases and I hadn't noticed this.

我正在开发一个应用程序,它显示一些子窗口,用户可以关闭它们,也可以自动关闭它们。在调试抛出的一些异常时,我发现我试图调用已经关闭的窗口上的Hide()等方法;这个特定的代码分支对这两种情况都是通用的,我没有注意到这一点。

One of my first ideas was to look for a property on Window that would indicate the window had been closed. I can't seem to find one. In WinForms, I'd look to the IsDisposed property for a somewhat reliable indicator that the form had been closed (it won't reliably work for a dialog but I'm not working with dialogs.) I don't see anything equivalent on Window. The documentation for Window.Close() doesn't seem to indicate any properties that are changed by the method. Am I missing something obvious, or is the only method to know if a window's been closed to handle the Closed event? That seems kind of a harsh requirement for a simple task.

我最初的想法之一是在窗户上寻找一个属性,表明窗户已经关闭。我好像找不到。在WinForms中,我将查看isdump属性,以获得某种可靠的指示,该指示表已关闭(它不会可靠地为对话框工作,但我不使用对话框)。我在窗户上看不到任何相似的东西。Window.Close()的文档似乎不表示方法更改的任何属性。我是否遗漏了一些明显的东西,或者是唯一知道窗口是否已关闭以处理关闭事件的方法?这似乎是对一个简单任务的苛刻要求。

7 个解决方案

#1


45  

According to this conversation on the MSDN WPF forums (see the last post), you can check to see if the IsLoaded is false, which means that the window is "eligible" for unloading its content. I hope that works for you!

根据MSDN WPF论坛上的对话(见最后一篇文章),您可以检查IsLoaded是否为false,这意味着窗口“有资格”卸载它的内容。我希望这对你有用!

#2


7  

Another way : Application.Windows contains a list of open windows. You can check is this collection contains your window (it is removed after closing).

另一种方法:应用程序。Windows包含一个打开的窗口列表。您可以检查这个集合是否包含您的窗口(它在关闭后被删除)。

Looks like you have to call OfType<Window>() because it is a specialized collection.

看起来您必须调用OfType (),因为它是一个专门的集合。

#3


5  

If you derive from the Window class, you can do this:

如果从窗口类派生,可以这样做:

public bool IsClosed { get; private set; }

protected override void OnClosed(EventArgs e)
{
    base.OnClosed(e);
    IsClosed = true;
}

It has an advantage over registering for the Closed event - no need to un-register the callback.

它的优点是注册了闭事件——不需要取消回调。

#4


4  

My solution was to simply attach an event to the dialog's Closed event:

我的解决方案是将一个事件附加到对话框的关闭事件:

MikesDialog dlg = new MikesDialog();
dlg.Closed += delegate
{
    //  The user has closed our dialog.
    validationgDlg = null;
};

//  ...elsewhere in the code...

if (validationgDlg != null)
{
     //  Our "MikesDialog" is still open...
     . . .
}

#5


3  

Hope this is useful for you:

希望这对你有用:

PresentationSource.FromVisual(window) == null;

PresentationSource.FromVisual(窗口)= =零;

#6


3  

I don't know why the IsDisposed property is internal, but if you don't fear reflection:

我不知道为什么这些属性是内部的,但如果你不害怕反射:

var window = new Window();
var propertyInfo = typeof(Window).GetProperty("IsDisposed", BindingFlags.NonPublic | BindingFlags.Instance);
var isDisposed = (bool)propertyInfo.GetValue(window);

That being said, reflection is not to be overused because you're no longer protected by the public API of the class. Be sure to use at least unit tests if you go that route.

也就是说,反射不能被过度使用,因为您不再受到类的公共API的保护。如果您采用这种方法,请确保至少使用单元测试。

#7


0  

You can add a non static property to the WindowClass bool IsClosed, and set true on the Closed event:

您可以向WindowClass bool IsClosed添加一个非静态属性,并在关闭事件上设置true:

public partial class MyWindow : Window
{
    public bool IsClosed { get; set; } = false;
    public MyWindow()
    {
        Closed += MyWindow_Closed;
        InitializeComponent();
    }
}    

private void MyWindow_Closed(object sender, EventArgs e)
{
   IsClosed = true;
}

#1


45  

According to this conversation on the MSDN WPF forums (see the last post), you can check to see if the IsLoaded is false, which means that the window is "eligible" for unloading its content. I hope that works for you!

根据MSDN WPF论坛上的对话(见最后一篇文章),您可以检查IsLoaded是否为false,这意味着窗口“有资格”卸载它的内容。我希望这对你有用!

#2


7  

Another way : Application.Windows contains a list of open windows. You can check is this collection contains your window (it is removed after closing).

另一种方法:应用程序。Windows包含一个打开的窗口列表。您可以检查这个集合是否包含您的窗口(它在关闭后被删除)。

Looks like you have to call OfType<Window>() because it is a specialized collection.

看起来您必须调用OfType (),因为它是一个专门的集合。

#3


5  

If you derive from the Window class, you can do this:

如果从窗口类派生,可以这样做:

public bool IsClosed { get; private set; }

protected override void OnClosed(EventArgs e)
{
    base.OnClosed(e);
    IsClosed = true;
}

It has an advantage over registering for the Closed event - no need to un-register the callback.

它的优点是注册了闭事件——不需要取消回调。

#4


4  

My solution was to simply attach an event to the dialog's Closed event:

我的解决方案是将一个事件附加到对话框的关闭事件:

MikesDialog dlg = new MikesDialog();
dlg.Closed += delegate
{
    //  The user has closed our dialog.
    validationgDlg = null;
};

//  ...elsewhere in the code...

if (validationgDlg != null)
{
     //  Our "MikesDialog" is still open...
     . . .
}

#5


3  

Hope this is useful for you:

希望这对你有用:

PresentationSource.FromVisual(window) == null;

PresentationSource.FromVisual(窗口)= =零;

#6


3  

I don't know why the IsDisposed property is internal, but if you don't fear reflection:

我不知道为什么这些属性是内部的,但如果你不害怕反射:

var window = new Window();
var propertyInfo = typeof(Window).GetProperty("IsDisposed", BindingFlags.NonPublic | BindingFlags.Instance);
var isDisposed = (bool)propertyInfo.GetValue(window);

That being said, reflection is not to be overused because you're no longer protected by the public API of the class. Be sure to use at least unit tests if you go that route.

也就是说,反射不能被过度使用,因为您不再受到类的公共API的保护。如果您采用这种方法,请确保至少使用单元测试。

#7


0  

You can add a non static property to the WindowClass bool IsClosed, and set true on the Closed event:

您可以向WindowClass bool IsClosed添加一个非静态属性,并在关闭事件上设置true:

public partial class MyWindow : Window
{
    public bool IsClosed { get; set; } = false;
    public MyWindow()
    {
        Closed += MyWindow_Closed;
        InitializeComponent();
    }
}    

private void MyWindow_Closed(object sender, EventArgs e)
{
   IsClosed = true;
}