4

我试图在打开一个新公式时关闭一个公式。关闭公式时,我想在关闭事件中处理一些特殊逻辑。但是关闭事件永远不会被调用,无论是在 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);
    }
 }
4

4 回答 4

6

这是不正常的行为,因为本机 Windows MDI 实现不支持隐藏 MDI 子窗口。Winforms 使用了一个技巧来仍然支持 Hide(),它实际上会破坏本机窗口并在您再次调用 Show() 时重新创建它。然而,这有一个副作用,Close() 调用不再引发 FormClosing/Closed 事件,因为本机窗口已被 Hide() 调用销毁。这是一个错误,在 Winforms 中并不少见。

解决方法很简单,调用 Close() 时不需要 Hide(),只需将其删除即可。

于 2012-01-09T17:48:21.303 回答
1

好吧,我一直在战斗并找到了解决方案

if (_currentForm != null && !_currentForm.IsDisposed)
{
    // This call prevents calling the closing event -> _currentForm.Hide();
    _currentForm.Close();
}

这是 Windows 窗体 ._。

于 2012-01-09T17:10:19.910 回答
0

你可以试试这个:

form1.Closing += delegate 
{
  // your logic
};
于 2012-01-09T17:04:18.837 回答
0

这篇文章对我也很有用,尽管我的情况略有不同。

在这种情况下,避免_currentForm.Hide();工作正常,因为代码执行了表单切换。我发现问题也源于一个 MDIChild,该 MDIChild 已被位于顶部的不同 MDIChild 隐藏。

这是一种解决方法,在这种情况下也适用,基于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 {

考虑到这在任何情况下都是一种工作。主要区别在于 set在从 Disposed 作为备份调用e.Cancel=true的情况下无效。FormClosing

于 2013-01-05T21:52:49.433 回答