为什么在模态对话框中调用 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 方法。
有关更多信息,请查看:
您提到的解决方法是不必要的,因为模式对话框在关闭时不会被释放。它们旨在在关闭后保留其数据(因为模态对话框的调用者需要它),并根据需要重复使用。
让它正常关闭就好了。它不会对模态对话框造成伤害 :)
请注意,这也意味着与普通表单不同,您必须 手动处理非持久性模式对话框。在您的场景中,这很可能意味着您希望在处理父表单时处理对话框(如果您将对话框添加为组件,这会自动发生,但如果您自己创建它,则需要手动完成)。
我们创建了一个通过 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()
,该事件将再次引发。
想象一下,如果它没有关闭表单,您的应用程序就会被隐藏的模态表单阻止!
注意:答案描述了引发两次事件的原因。但是正如
有关更多信息,请查看:
您提到的解决方法是不必要的,因为模式对话框在关闭时不会被释放。它们旨在在关闭后保留其数据(因为模态对话框的调用者需要它),并根据需要重复使用。
让它正常关闭就好了。它不会对模态对话框造成伤害 :)
请注意,这也意味着与普通表单不同,您必须 手动处理非持久性模式对话框。在您的场景中,这很可能意味着您希望在处理父表单时处理对话框(如果您将对话框添加为组件,这会自动发生,但如果您自己创建它,则需要手动完成)。