为什么在模态对话框中调用 Hide() 时 FormClosing 会触发两次?

Why does FormClosing fire twice when calling Hide() in modal dialog?

我们创建了一个通过 ShowDialog 显示的新表单,并向其添加了一个 "Cancel" 按钮。以下是我们从其父级打开表单的方式:

// _modalForm is a class-level instance of our ModalForm class
var result = _modalForm.ShowDialog(this);
MessageBox.Show(result.ToString());

这是 ModalForm 中取消按钮的 Click 事件处理程序。

private void btnCancel_Click(object sender, EventArgs e)
{
    Close();
}

在我们的 FormClosing 事件中,我们有这段代码(基于 this answer)。

private void ModalForm_FormClosing(object sender, FormClosingEventArgs e)
{
        e.Cancel = true;
        Hide();
        _parentForm.RefreshData();
}

令人惊讶的是,当我们单击 "Cancel" 按钮(或使用窗体顶部的 "X" 按钮)时,会引发两次 FormClosing 事件。 CloseReason 两次都是 UserClosing.

我仔细检查以确保 InitializeComponent 没有调用两次并且我们只订阅了一次事件。 btnCancel 未在表单的 CancelButton 属性 处设置。它也没有在设计器中设置 DialogResult 。但是,当我检查 ShowDialog 的 return 值时,它被设置为 DialogResult.Cancel.

btnCancel_Click 更改为 DialogResult = DialogResult.Cancel 而不是 Close() 并在 FormClosing 事件中除了 _parentForm.Refresh() 什么都不做,解决了事件获取的问题筹集了两次。

有谁知道为什么在这种特定情况下 FormClosing 事件会引发两次?

那是因为隐藏模态窗体会导致它以 DialogResult.Cancel 作为对话框结果关闭。因此,如果您在 FormClosing 事件中调用 this.Hide(),该事件将再次引发。

想象一下,如果它没有关闭表单,您的应用程序就会被隐藏的模态表单阻止!

注意:答案描述了引发两次事件的原因。但是正如 和其他人提到的那样,对于模态表单(您使用 ShowDialog 显示),不会调用 Dispose 方法并且表单在关闭后存在,您可以使用它的属性获取一些数据或者您可以显示再次。所以你不需要调用 hide 方法。

有关更多信息,请查看:

您提到的解决方法是不必要的,因为模式对话框在关闭时不会被释放。它们旨在在关闭后保留其数据(因为模态对话框的调用者需要它),并根据需要重复使用。

让它正常关闭就好了。它不会对模态对话框造成伤害 :)

请注意,这也意味着与普通表单不同,您必须 手动处理非持久性模式对话框。在您的场景中,这很可能意味着您希望在处理父表单时处理对话框(如果您将对话框添加为组件,这会自动发生,但如果您自己创建它,则需要手动完成)。