【发布时间】:2018-01-30 10:15:49
【问题描述】:
我有一个非常简单的 WinForms 应用程序,它由三个表单组成:Form1、Form2 和 Form3。 Form1 是主应用程序窗口。通过点击此窗口中的按钮,用户通过调用ShowDialog(this) 将Form2 作为模式对话框打开。同样,Form2 有另一个按钮,它通过对ShowDialog(this) 的另一个调用打开 Form3。在每种情况下,this 分别指向托管来自:Form1 和 Form2。
在 Form3 中的 user hist OK 按钮之前,一切正常。此时 Form3 和 Form2 模态窗口都关闭,用户返回 Form1。从逻辑上讲,用户应该返回到 Form2,从那里他或她启动了 Form3。为什么会发生?谢谢。
Form1 在以下代码中打开 Form2:
private void form1_ButtonClick(object sender, EventArgs e)
{
Form2 settings = new Form2();
DialogResult result = settings.ShowDialog(this);
if (result == DialogResult.OK)
{ }
}
然后Form2在这段代码中打开Form3:
private void form2_ButtonClick(object sender, EventArgs e)
{
Form3 settings = new Form3();
DialogResult result = settings.ShowDialog(this);
if (result == DialogResult.OK)
{ }
}
有趣的是,退出函数 form2_ButtonClick() 后的调试器会立即进入 form1_ButtonClick() 作为下一步。我检查了处理程序的所有调用,没有看到任何与表单关闭相关的代码。即使当我评论我们所有的处理程序代码时,表单仍然在级联中关闭。
我怀疑表单关闭是由于对话框结果分配给表单按钮,所以我禁用了两者并添加了显式按钮处理程序。结果保持不变。另外,我在这两个函数中都注释掉了对话结果的所有处理。尽管如此,关闭 Form3 也会神奇地关闭其父 Form2 并直接进入 Form1。
按照建议,我还添加了显式 Form2.FormClosing() 处理程序并将断点放在那里。是的,在关闭 Form3 时会立即调用此处理程序,而无需任何代码提示此调用。
解决方案(部分)
找不到原因,我听从了@Otterprinz 的宝贵建议并修改了如下处理程序。
private bool allowClose = true;
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
if (!allowClose)
{
e.Cancel = true;
allowClose = true;
}
}
在显示 Form3 之前,我分配了allowClose = false。它可以工作并防止 Form2 突然关闭。为什么会发生这种情况我不知道。表格一点也不复杂。我仔细检查了他们的源代码,没有发现任何错误。这些不是我设计的第一个,甚至不是第 100 个表格。以前从未见过这种效果。但是,由于您的宝贵建议,至少我找到了解决方案。谢谢大家的cmets!
【问题讨论】:
-
如果没有真实的代码示例,我认为我们只能猜测。
-
在 Form2.FormClosing 上放置一个事件处理程序并在其中放置一个断点。如果是您的代码执行此操作,则会显示调用堆栈。
-
@Otterprinz,谢谢。用你的想法更新了问题文本,但没有任何影响。
-
@Otterprinz,我倾向于接受您的解决方案,然后输入“e.Cancel = true;”进入 FormClosing() 处理程序。唯一的问题是区分结束通话的位置。如果普遍应用,表单原则上是不可能关闭的!
-
@BorisZinchenko 我喜欢寻找原因,但我不知道你的日程安排,所以有时“它比以前工作得更好”就足够了。