代码之家  ›  专栏  ›  技术社区  ›  Noam Gal

WinForm在释放窗体时释放子窗体

  •  0
  • Noam Gal  · 技术社区  · 17 年前

    我有一个可以打开子窗体的窗体 ShowDialog )我要确保在完成主窗体时正确地处理子窗体。 我尝试将子窗体添加到 components 是主窗体的成员,但现在我有一个 ArgumentNullException .
    我知道我可以举例说明 组件 我自己,但那不是有点危险吗?有一天,我将在设计器视图中添加一个组件,它将生成 new Container() 行在designer.cs文件中,我永远不会知道堆中有两个组件实例。
    是否有更简单的方法来确保子窗体被释放?

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

    4 回复  |  直到 15 年前
        1
  •  3
  •   Spence    17 年前

    如果您在ShowDialog中使用表单,可以假设在收到结果后,您可以在那里处置表单?

    using(MyDialog dlg = new MyDialog())
    {
       result = dlg.ShowDialog();
    }
    
        2
  •  1
  •   Rauhotz    17 年前

    通常不能重写窗体的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;
            }
        }
    

    保留子窗体列表,并将以下行添加到主窗体的构造函数中:

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

    当您的主窗体被释放时,所有子窗体也将被释放,例如:

    private void MyDisposeAction(bool disposing)
    {
      if (disposing)
      {
        foreach (var subForm in this.subForms)
        {
          subForm.Dispose(disposing);
        }
      } 
    }
    
        3
  •  0
  •   Cerebrus    17 年前

    按照 MSDN ,通过调用模式窗体 ShowDialog() 不会自动释放,开发人员有责任释放它们:

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

    这里的相关点是“当不再需要表格时”。在您的情况下,您似乎需要将表单用于后续操作,因此包装 显示对话框() 打电话 using 构造不能达到目的。

    我的建议是在主窗体的Dispose方法中释放对话框,或者尽早:

    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);
    }
    
        4
  •  0
  •   Noam Gal    17 年前

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

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