我需要帮助解决下面的问题。
我正在创建一个带有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;
...
}
非常感谢有关如何解决此问题的任何建议。
答案 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)
当表单关闭时,在对象中创建的所有资源都是 关闭,表格处理。您可以阻止关闭表单 在运行时通过处理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();
...
}