表格处理时WinForm处理子表单

时间:2009-06-01 07:16:06

标签: c# winforms dispose

我有一个可以打开子表单的表单(ShowDialog)。我想确保在完成主表单时正确处理子表单。 我尝试将子表单添加到主表单的components成员中,但此刻我得到了ArgumentNullException
我知道我可以自己实例化components,但这有点危险吗?有一天,我将在设计器视图中添加一个组件,这将在designer.cs文件中生成new Container()行,我永远不会知道我有两个组件实例在堆中运行。
有没有更简单的方法来确保子表格被处理?

编辑 - 将我的解决方案移至答案

4 个答案:

答案 0 :(得分:3)

如果您在showdialog中使用该表单,可以假设在收到结果后您可以在那里处理该表单吗?

using(MyDialog dlg = new MyDialog())
{
   result = dlg.ShowDialog();
}

答案 1 :(得分:1)

您通常无法覆盖表单的Dipose方法,因为它已在Form.Designer.cs文件中定义。如何将自己的处置逻辑添加到表单中有一个小技巧。

使用以下课程:

public class Disposer : Component
    {
        private readonly Action<bool> disposeAction;               

        public Disposer(Action<bool> disposeAction)
        {
            this.disposeAction = disposeAction;
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            this.disposeAction(disposing);
        }

        public static Disposer Register(ref IContainer container, Action<bool> disposeAction)
        {
            Disposer disposer = new Disposer(disposeAction);
            if (container == null)
                container = new System.ComponentModel.Container();

            container.Add(disposer);
            return disposer;
        }
    }

保留一个子表单列表,并将以下行添加到mainform的构造函数中:

Disposer.Register(ref this.components, this.MyDisposeAction);

当您的主要形式被处置时,您的所有子形态也将被处置,例如:

private void MyDisposeAction(bool disposing)
{
  if (disposing)
  {
    foreach (var subForm in this.subForms)
    {
      subForm.Dispose(disposing);
    }
  } 
}

答案 2 :(得分:0)

根据MSDN,通过ShowDialog()调用的模态表单不会自动处理,开发人员有责任处置它们:

  

当窗体显示为模式对话框时,单击“关闭”按钮(窗体右上角带有X的按钮)会导致隐藏窗体并将DialogResult属性设置为DialogResult。取消。与无模式窗体不同,当用户单击对话框的关闭窗体按钮或设置DialogResult属性的值时,.NET Framework不会调用Close方法。而是隐藏表单,并且可以在不创建对话框的新实例的情况下再次显示该表单。因为显示为对话框的表单未关闭,所以当应用程序不再需要该表单时,必须调用表单的Dispose方法。

这里的相关点是“当不再需要表格时”。在您的情况下,您似乎需要用于后续操作的表单,因此将ShowDialog()调用包装在using构造中将无法实现此目的。

我的建议是在主表单的Dispose方法中处理Dialog,或者尽早处理:

protected override void Dispose(bool disposing)
{
  if (disposing && (components != null))
  {
    components.Dispose();
  }
  // dlg is a variable of type Form2(the dialog)
  if (dlg != null)
  {
    dlg.Dispose();
    dlg = null;
  }
  base.Dispose(disposing);
}

答案 3 :(得分:0)

我目前的解决方法:
我已将Components属性添加到表单中,并使用它来访问集合

private IContainer Components{    get { return components ?? (components = new Container());}}