关闭并从另一个类引用时,Form不会变为null

时间:2012-05-10 17:47:21

标签: c# winforms

我需要帮助解决下面的问题。

我正在创建一个带有MDI接口的Windows窗体应用程序。在我的应用程序中,我创建了一个基本上处理所有子窗体的所有打开/关闭的类,我们称之为 FManage 。此外,它还会检查表单实例是否已打开。如果是这样,它不会让用户打开表单的另一个实例。这是我的问题所在。 当用户要求打开一个窗口时, FManage 以下代码:

if (frm1 == null)
{
    frmOne = new frm1();
    frmOne.MdiParent = Main.ActiveForm; //Main is the parent form
}
frmOne.Show();

现在,这个代码在首次打开窗口时工作正常。说 frm1 已关闭,并要求再次打开。上面的代码再次执行,但 frm1 不等于NULL。我在 FManage 类的上面的代码中设置了一个断点,它显示 frm1 != null,即使 frm1 已关闭。我认为问题是 frm1 ,因为它存储为 FManage 中的参考,并不是说 FManage 它是空的。 FManage 只存储表单的初始状态,类似于静态变量。 我是OOP的新手,我真的在寻找解决这个问题的最佳方法。

我的第一个解决方案是,在 frm1 关闭之前,可能在FormClosing事件中,将消息发送回 FManage 类以设置 frm1 为null;但是,为了做到这一点, frm1 类需要知道 FManage ,现在它不会。 FManage 了解 frm1 ,而不是相反。分享不是相互的。 仅供参考, frm1 定义为我的类定义后的方法:

public class FManage
{
    frmOne frm1;
 ...
}

非常感谢有关如何解决此问题的任何建议。

7 个答案:

答案 0 :(得分:6)

解决问题的关键是FormClosing事件的子类化 在您打开表单时为该事件设置处理程序 然后在那个事件中(如果你同意关闭)将你的全局变量设置为null 这将正确重置您的逻辑以打开frmOne的新 INSTANCE 不要将frmOne(类)与frm1(frmOne的实例)混淆

public class FManage 
{ 
    frmOne frm1; 
    ... 

    // Here test on frm1 and create a new instance of frm1
    if (frm1 == null) 
    { 
        frm1 = new frmOne(); 
        frm1.FormClosing += fManage_FormOneClosing;
        frm1.MdiParent = Main.ActiveForm; 
    } 
    frm1.Show(); 

    ...

    public void fManage_FormOneClosing(object sender, FormClosingEventArgs e) 
    {
        ... (check if you agree to close the form frm1

        // set the instance of frmOne captured in the global var to null....
        frm1 = null;
    }
} 

答案 1 :(得分:2)

Form就像任何其他对象一样是一个对象。它的寿命是否仍然可以控制。因此,隐藏(关闭)表单永远不会破坏对象或将任何内容设置为null

您需要处理表单的FormClosed事件才能知道它何时关闭。

答案 2 :(得分:1)

From MSDN

  

当表单关闭时,在对象中创建的所有资源都是   关闭,表格处理。您可以阻止关闭表单   在运行时通过处理Closing事件并设置Cancel   CancelEventArgs的属性作为参数传递给您的事件   处理程序。如果您要关闭的表单是您的启动表单   申请,你的申请结束。

     

表单未在关闭时处理的两个条件是(1)它   是多文档界面(MDI)应用程序的一部分,而且是   形式不可见; (2)您已使用表格显示   ShowDialog的。在这些情况下,您需要手动调用Dispose   标记所有表单的垃圾收集控件。

答案 3 :(得分:1)

一个选项是按照您的描述处理FormClosing事件。您不需要表格来“了解”FManage。你可以让FManage订阅这样的活动:

frm1.FormClosing += this.FormClosing; // this is FManage

另一个选项是在创建子表单时检查表单的Visible属性是否为true。

if (frmOne == null || !frmOne.Visible)
{
    frmOne = new frm1();
    frmOne.MdiParent = Main.ActiveForm; //Main is the parent form
}
else
{
    // form is already created.  maybe bring to front?
    frmOne.BringToFront();
}

答案 4 :(得分:0)

如果frmOne没有超出范围,它就不会被处理掉。它会保留你给它的任何值(在这种情况下是frm1的一个实例)。如果需要,可以在每次需要时创建一个新的frm1对象。

答案 5 :(得分:0)

另一个解决方案是迭代My.Application.OpenForms集合以检查表单是否已打开 当调用onFormClosed内部方法/事件时,它们将从此集合中删除。

答案 6 :(得分:0)

您可以使用lambda:

public class FManage 
{ 
    frmOne frm1; 
    ... 

    // Here test on frm1 and create a new instance of frm1
    if (frm1 == null) 
    { 
        frm1 = new frmOne(); 
        frm1.FormClosing += (sndr, evnt) => { frm1 = null; };
        frm1.MdiParent = this; 
    } 
    frm1.Show(); 

    ...

}