我如何回复最后一个MDI子表格结束?

时间:2014-01-24 15:24:56

标签: c# winforms events mdi

我的目标是响应mdi容器关闭的最后一个子窗体(例如,关闭父本身或显示新内容)。我面临的问题是mdi容器的MdiChildren集合仍然表明容器包含子容器。

我尝试的方法是

void childMdiForm_FormClosed(object sender, FormClosedEventArgs e)
{
    if (this.MdiChildren.Any())
    {
        //Do stuff
    }
}
最后一个子表单关闭后,

MdiChildren.Count()仍为1。

尝试处理parentform.MdiChildActivate事件时,我的结果相同。

当子表单关闭时,MdiChildren集合似乎尚未更新。当有多个孩子时会发生同样的情况:它仍然包含所有的孩子,它似乎会在稍后更新集合。

这是正确的做法吗?如果没有,我怎样才能在关闭表格后准确计算mdi孩子的数量?

5 个答案:

答案 0 :(得分:3)

是的,在传递FormClosed事件之后,MdiChildren属性才会更新。对于像这样的事件顺序问题,有一个通用的解决方案,您可以通过使用Control.BeginInvoke()方法优雅地获取在事件处理完成后运行的代码。此代码解决了您的问题:

protected override void OnMdiChildActivate(EventArgs e) {
    base.OnMdiChildActivate(e);
    this.BeginInvoke(new Action(() => {
        if (this.MdiChildren.Length == 0) {
            // Do your stuff
            //...
            MessageBox.Show("None left");
        }
    }));
}

答案 1 :(得分:2)

WinForms有时会有点古怪,这就是一个例子。我不完全确定为什么关闭最后一个MDI子项不会使MdiChildren属性立即返回一个空数组。

在大多数情况下,您将自己跟踪子窗体或数据模型,因此我只需保留一个本地阵列来管理它:

    List<Form> childForms = new List<Form>();

    void AddChildWindow()
    {
        var window = new ChildForm();
        window.MdiParent = this;
        window.Tag = Guid.NewGuid();

        window.FormClosed += (sender, e) => { OnMdiChildClosed(sender as Form, e.CloseReason); };
        window.Shown += (sender, e) => { OnMdiChildShown(sender as Form); };

        window.Show();
    }

    void OnMdiChildShown(Form window)
    {
        childForms.Add(window);

        Trace.WriteLine(string.Format("Child form shown: {0}", window.Tag));
        Trace.WriteLine(string.Format("Number of MDI children: {0}", childForms.Count));
    }

    void OnMdiChildClosed(Form window, CloseReason reason)
    {
        childForms.Remove(window);

        Trace.WriteLine(string.Format("Child form closed: {0} (reason: {1})", window.Tag, reason));
        Trace.WriteLine(string.Format("Number of MDI children: {0}", childForms.Count));

        if (childForms.Count == 0)
        {
             // Do your logic here.
        }
    }

答案 2 :(得分:1)

这是一个完整的测试示例:

namespace WindowsFormsApplication1
{
    public partial class mdiMainForm : Form
    {
        private List<Form> _children = new List<Form>();

        public mdiMainForm()
        {
            InitializeComponent();
        }

        private void mdiMainForm_Shown(Object sender, EventArgs e)
        {
            Form3 f3 = new Form3();
            f3.MdiParent = this;
            f3.FormClosed += mdiChildClosed;
            _children.Add(f3);
            f3.Show();
            Form4 f4 = new Form4();
            f4.MdiParent = this;
            f4.FormClosed += mdiChildClosed;
            _children.Add(f4);
            f4.Show();
            Form5 f5 = new Form5();
            f5.MdiParent = this;
            f5.FormClosed += mdiChildClosed;
            _children.Add(f5);
            f5.Show();
        }

        private void mdiChildClosed(Object sender, FormClosedEventArgs e)
        {
            if (_children.Contains((Form)sender))
                _children.Remove((Form)sender);
            if (_children.Count == 0)
                MessageBox.Show("all closed");
        }
    }
}

答案 3 :(得分:0)

您的代码似乎暗示您正在检查子Form的MdiChildren集合。但也许我误读了你的代码。

使用MDI表单的'MdiChildActivate'事件:

private void Form1_MdiChildActivate(object sender, EventArgs e) {
    if(this.MdiChildren.Length == 0) {
        // replace with your "Do Stuff" code
        MessageBox.Show("All Gone");
    }
}

答案 4 :(得分:0)

我知道这个答案很晚,但我对这个问题的解决方案要比提供的解决方案简单得多,所以我会在这里分享。

$allowedTypes = ['video', 'image', 'audio'];
...
if ( in_array(
    explode("/", 
        mime_content_type($_FILES['fileToUpload1']["tmp_name"][$counter])
    )[0],
    $allowedTypes) )