关闭一个子窗体会关闭其他子窗体。

4
在以下代码中,Form1打开了另外两个Form,然后关闭了其中一个。结果是第二个子窗体也被关闭了。为什么会这样呢?
public partial class Form1 : Form
{
    System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer { Interval = 2000 };

    public Form1()
    {
        InitializeComponent();
        ShowForm3();
        (new Form2()).ShowDialog();//If this is changed to 'Show' - it doesn't get closed.
    }

    void ShowForm3()
    {
        Form3 f3 = new Form3();
        f3.Show();
        timer.Tick += (sender, e) => f3.Close();
        timer.Start();
    }
}

Form2Form3是默认的VS表单。

(另外:这是原始代码的简化版本。在原始代码中,当在Visual Studio中执行时(无论是Debug还是Release),不会发生这种情况。只有当安装为ClickOnce应用程序后,即使我只是点击AppData文件夹下的可执行文件,它才会发生。(也许是代码中的其他部分在从VS中执行时阻止了它的发生,但我还没有找到具体原因。)什么可能引起这种差异?Maybe clickonce中存在某种优化,在常规Release模式下没有做到?)


现在是打开 Reflector 的时候了。 - Sriram Sakthivel
@SriramSakthivel 我想你是指最后一段。好主意。谢谢。 - ispiro
不,我可以在VS本身中再现。 - Sriram Sakthivel
1个回答

5
将您的代码更改为以下可行的代码:
  public partial class Form1 : Form
  {
    System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer { Interval = 2000 };

    public Form1()
    {
        InitializeComponent();
        ShowForm3();
        (new Form2()).ShowDialog(this);
    }

    void ShowForm3()
    {
        Form3 f3 = new Form3();
        f3.Show();
        timer.Tick += (sender, e) => f3.Close();
        timer.Start();
    }
  }

解释:当您没有传递表单父级时,窗口将使用此方法将活动窗口作为父级:GetActiveWindow,所发生的情况是:

当调用form2.showDialog() // 父窗口是form 3,因为GetActiveWindow方法获取正在显示的窗口,而form1不是活动或正在显示的窗口

当您强制指定父级时: 当调用form2.showDialog(this) // 父窗口是form 1,因为您定义了固定值


你能解释一下吗?为什么这个可以工作,而那个不行? - Sriram Sakthivel
运行旧代码而不启动计时器。中断并查看Form3的父级是什么。我怀疑父级已经设置为Form2(因为在显示Form3时它是最上层的窗体)。 - Hamish Smith
谢谢。不过需要注意的是:虽然文档与您的说法一致,但在我的版本中,实际上Owner为空。您可以通过在Tick处理程序中添加MessageBox.Show(f2.Owner.Text);来查看这一点。 - ispiro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接