【问题标题】:WinForms cascading modal dialogsWinForms 级联模式对话框
【发布时间】: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 我喜欢寻找原因,但我不知道你的日程安排,所以有时“它比以前工作得更好”就足够了。

标签: c# winforms


【解决方案1】:

在一个 winform 项目上进行了测试,它按预期工作。 Asker 的代码可能与他发布的代码不同(等效)。

    // form1,form2,form3 are default forms
    // form1 button handler 
    private void button1_Click(object sender, EventArgs e)
    {
        Form2 form = new Form2();
        DialogResult result = form.ShowDialog(this);
    }

    // form2 button handler
    private void button1_Click(object sender, EventArgs e)
    {
        Form3 form = new Form3();
        DialogResult result = form.ShowDialog(this);
    }

当关闭时,form3 将焦点和控制权返回给 form2。 gif 显示行为https://media.giphy.com/media/3ohs4lqu1NIy4i7hEA/giphy.gif

【讨论】:

    【解决方案2】:
    Form2 settings = new Form2();
    DialogResult result = settings.ShowDialog(this);
    // ShowDialog will wait settings close
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-26
      • 2015-09-19
      • 1970-01-01
      • 2011-12-19
      相关资源
      最近更新 更多