2

我需要帮助解决以下问题。

我正在创建一个带有 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;
 ...
}

任何有关如何解决此问题的建议将不胜感激。

4

7 回答 7

6

解决问题的关键是 FormClosing 事件的子类化。
仅在您打开表单时为该事件设置一个处理程序。
然后在那种情况下(如果您同意关闭)将您的全局变量设置为空。
这将正确重置您的逻辑以打开一个新的frmOne 实例
不要将 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;
    }
} 
于 2012-05-10T17:59:20.540 回答
2

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

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

于 2012-05-10T17:50:54.100 回答
1

来自 MSDN

当窗体关闭时,对象内创建的所有资源都将关闭并释放窗体。您可以通过处理 Closing 事件并设置作为参数传递给事件处理程序的 CancelEventArgs 的 Cancel 属性来防止在运行时关闭窗体。如果您要关闭的表单是应用程序的启动表单,则您的应用程序将结束。

表单未在 Close 上处理的两种情况是: (1) 它是多文档界面 (MDI) 应用程序的一部分,并且表单不可见;(2) 您已经使用 ShowDialog 显示了表单。在这些情况下,您将需要手动调用 Dispose 以将表单的所有控件标记为垃圾回收。

于 2012-05-10T17:52:59.607 回答
1

一种选择是按照您的描述处理 FormClosing 事件。您不需要表格即可“了解”FManage。您可以让 FManage 像这样订阅事件:

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

另一种选择是在创建子表单时检查表单的 Visible 属性是否为真。

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();
}
于 2012-05-10T17:54:21.027 回答
0

如果 frmOne 没有超出范围,它就不会被处理掉。它将保留您给它的任何值(在本例中为 frm1 的实例)。如果需要,您可以在每次需要显示时创建一个新的 frm1 对象。

于 2012-05-10T17:53:14.160 回答
0

另一种解决方案是遍历 My.Application.OpenForms 集合以检查表单是否打开。
当它们的 onFormClosed 内部方法/事件被调用时,它们将从这个集合中移除。

于 2012-11-09T16:55:44.940 回答
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(); 

    ...

} 
于 2014-06-05T07:27:08.853 回答