没有为MDI子窗体调用FormClosing事件
本文关键字:调用 FormClosing 事件 窗体 MDI | 更新日期: 2023-09-27 18:19:47
打开一个新的公式时,我正试图关闭一个公式。当关闭一个公式时,我想在关闭事件中处理一些特殊的逻辑。但是无论是在FormClosing中还是在closing事件中,无论是在抽象基类中还是在给定的手动附加事件form_FormClosing
中,都不会调用关闭事件。
当我通过单击x手动关闭表单时,所有事件都会被触发。调用Close()
方法失败。
你有什么建议来解决我的问题吗?
MdiParent:
private Form _currentForm;
private void ShowForm<T>() where T : Form
{
if (_currentForm != null && !_currentForm.IsDisposed)
{
_currentForm.Hide();
_currentForm.Close();
}
var form = MdiChildren.FirstOrDefault(f => f.GetType() == typeof(T));
if (form == null)
{
form = _formFactory.CreateForm<T>();
form.MdiParent = this;
form.WindowState = FormWindowState.Maximized;
form.FormClosing += form_FormClosing;
_currentForm = form;
MdiBackground.Hide();
form.Show();
}
else
{
ActivateMdiChild(form);
form.Activate();
}
}
void form_FormClosing(object sender, FormClosingEventArgs e)
{
// will not be called
}
抽象通用mdi子窗体:
public abstract partial class BaseForm<TEntity> : Form where TEntity : class, IEntity
{
protected override void OnClosing(CancelEventArgs e)
{
// wil not be called
if (EditMode == EditModes.Editable)
{
MessageBox.Show(this, "Please commit or abort your changes");
e.Cancel = true;
}
base.OnClosing(e);
}
}
这是因为本机Windows MDI实现不支持隐藏MDI子窗口。Winforms使用了一个技巧来仍然支持Hide(),它实际上会破坏本机窗口,并在您再次调用Show()时重新创建它。然而,这也有副作用,Close()调用不再引发FormClosing/Closed事件,因为本机窗口已经被Hide()调用破坏。这是一个bug,在Winforms中并不罕见。
解决方法很简单,调用Close()时不需要Hide(),只需将其删除即可。
我一直在战斗,找到了的解决方案
if (_currentForm != null && !_currentForm.IsDisposed)
{
// This call prevents calling the closing event -> _currentForm.Hide();
_currentForm.Close();
}
这是Windows Forms._。
你可以试试这个:
form1.Closing += delegate
{
// your logic
};
这篇文章对我也很有用,尽管我的情况略有不同。
在这种情况下,避免_currentForm.Hide();
工作得很好,因为代码进行了形式切换。我发现问题也源于一个MDIChild,它被顶部的另一个MDIC hild隐藏了。
基于Dispose
总是被调用的事实,这里有一个在这种情况下也有效的变通方法。
它可以做这样的准备:
public abstract class FormExtenderClass : Form{
private bool formClosingFired = false;
private bool formClosedFired = false;
protected override void OnFormClosing(FormClosingEventArgs e) {
base.OnFormClosing(e);
formClosingFired = !e.Cancel;
}
protected override void OnFormClosed(FormClosedEventArgs e) {
base.OnFormClosed(e);
formClosingFired = true;
}
protected override void Dispose(bool disposing) {
if (!formClosingFired) OnFormClosing(new FormClosingEventArgs(CloseReason.UserClosing, false));
if (!formClosedFired) OnFormClosed(new FormClosedEventArgs(CloseReason.UserClosing));
base.Dispose(disposing);
}
}
然后在MDIChildren的代码中,只需更改的第一行
public partial class AutoForm : Form {
至
public partial class AutoForm : FormExtenderClass {
无论如何,这都是一个令人担忧的问题。主要区别在于,在从Disposed调用FormClosing
作为备份的情况下,设置e.Cancel=true
将不起作用。