【问题标题】:How to override correctly OnFormClosing() method in C#如何在 C# 中正确覆盖 OnFormClosing() 方法
【发布时间】:2014-10-26 10:25:43
【问题描述】:

我有一个表单,其中有一个名为“搜索”的按钮。当我单击它时,会打开另一个表单来搜索项目。当用户在第二种形式中单击 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# formclosing


【解决方案1】:

您没有阻止它关闭,您忘记将 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,目前尚不清楚。

【讨论】:

    【解决方案2】:

    你真的不需要在这里覆盖任何东西。只需处理FormClosing 事件并设置e.Cancel = True。另外,让您的表单在同一个处理程序中不可见。在第一个表单中,创建第二个表单的类级别对象,并在单击“搜索”按钮时调用其ShowDialog()。最后确保您的 OKCancel 按钮的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();
        }
    }
    

    【讨论】:

    • 我理解 :D 但无论如何,这个解决方案意味着我总是运行主窗体,即使我不需要它,我也会创建第二个窗体,对吧?所以我认为我会假设消耗了不必要的资源。那个怎么样?值得吗?
    • @Drumnbass:考虑到我们今天的机器有过多的 RAM,我真的不会为节省那几 KB 的内存而烦恼。但是,我正在对上述代码进行更改以解决此问题。
    • 当然,我认为这只是几 KB 的内存,但请注意,我仍然是编程新手(只是一名学生),从现在开始我将开始获得良好的实践;)
    猜你喜欢
    • 1970-01-01
    • 2015-09-16
    • 1970-01-01
    • 2012-01-29
    • 2016-03-07
    • 2011-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多