如何在C#中正确重写OnFormClosing()方法

本文关键字:OnFormClosing 重写 方法 | 更新日期: 2023-09-27 18:27:55

我有一个表单,它有一个名为"搜索"的按钮。当我单击它时,会打开另一个表单来搜索项目。当用户点击第二个表单中的X来关闭它时,我并不真的希望它关闭,我只想让它不可见(通过secondForm.visible = false)。

我发现我需要的只是重写OnFormClosing()方法,我已经在表单类中完成了这些操作,但它根本没有执行。我知道它没有被执行,因为下次单击"搜索"按钮时(不是执行new SecondForm(),而是尝试执行secondForm.visible = true),我会得到一个异常,它说我不能处理已删除的对象(secondForm)或类似的东西。因此,第二个表单已经关闭,而不是不可见。

在这一点上,我开始认为我需要的是通过某种方式(我显然不知道),将这种新的覆盖方法分配给按钮X。

编辑:

这是我在类的第二个中高估的方法:

protected override void OnFormClosing(FormClosingEventArgs e)
    {
        base.OnFormClosing(e);
        if (e.CloseReason == CloseReason.WindowsShutDown) return;
        this.Visible = false;
    }

当点击"搜索"按钮时,我会这样做:

private void btnSearch_Click(object sender, EventArgs e)
    {
        if (subFormCreated)
            subFormSearch.Visible = true;
        else
            initializeSubFormSearch();
    }
    private void initializeSubFormSearch() 
    {
        subFormSearch = new SubForm(listaPersonas, actualMostrado);
        subFormSearch.Show();
        subFormCreated = true;
    }

最后,我得到的例外是ObjectDisposedException。确切的消息类似于(我不知道我是否正确地转换了它)ObjectDisposedException was unhandled. Cannot get access to the deleted object. Name of the object: SubForm.

如何在C#中正确重写OnFormClosing()方法

您没有阻止它关闭,忘记将e.Cancel属性设置为true。正确的代码是:

protected override void OnFormClosing(FormClosingEventArgs e) {
    if (e.CloseReason != CloseReason.WindowsShutDown) {
        this.Visible = false;
        e.Cancel = true;
    }
    base.OnFormClosing(e);
}

有了额外的细节,永远不想避免调用base。OnFormClosing(),当操作系统关闭时,您在自定义之后调用它,以便客户端程序可以在需要时否决您的决定。

通过订阅主类中的FormClosed事件,使其更有弹性,以便知道需要将subFormCreated变量设置为false。请注意,您不需要该变量,只需将subFormSearch变量设置回null即可。所以,大致来说:

private void displaySubFormSearch() {
    if (subFormSearch != null) {
        subFormSearch.WindowState = WindowState.Normal;
    }
    else {
        subFormSearch = new SubForm(listaPersonas, actualMostrado);
        subFormSearch.FormClosed += delegate { subFormSearch = null; };
    }
    subFormSearch.Show();
}

通过额外的细节,您可以确保在用户之前最小化窗口的情况下恢复窗口。现在它是坚实的。您可能需要属性来传递更新的listaPersonas和actualMostrado,这还不清楚。

您真的不需要覆盖这里的任何内容。只需处理FormClosing事件并设置e.Cancel = True即可。另外,使表单在同一处理程序中不可见。在第一个表单中,创建第二个表单的类级对象,并在单击"搜索"按钮时调用其ShowDialog()。最后,确保您的确定取消按钮的DailogResult属性设置正确。大致看起来是这样的:

class Form1
{
     private Form2 dlg;
    private void btnSearch_Click(object sender, EventArgs e)
    {
        if(dlg==null) dlg = new Form2();
        dlg.ShowDialog(this);
    }
}
class Form2
{
    private void Form2_FormClosing(object sender, FormClosingEventArgs e)
    {
        e.Cancel = true;
        this.Hide();
    }
}