点击“首页”按钮的时候,关闭所有子窗体:
            Form activeChild = this.ActiveMdiChild;
            if (activeChild != null)
            {
                while (activeChild != null)
                {
                    activeChild.Close();
                    activeChild.Dispose();
                    activeChild = this.ActiveMdiChild;
                }
            }这里把所有的子窗体关闭了然后再点击某个按钮,显示某个子窗体:
            if (FORM2 == null)
            {
                FORM2 = new form2();
                FORM2.MdiParent = this;
                FORM2.Show();
            }
            else
            {
                FORM2.Activate();
                FORM2.TopMost = true;
            }这里问题来了:在判断if (FORM2 == null) 的时候,为false,直接执行Else了。
我跟踪代码,在activeChild.Dispose();执行后,activeChild 和 this.ActiveMdiChild 都为null了,但是FORM2还是存在的。这样就导致了后面的判断不为null。
那么我想问一下,应该在哪里设置FORM2为null?可以在form2的Closed事件中设置吗?好像没办法写这个语句啊?

解决方案 »

  1.   


            #region MDI子窗体实例化一次
            /// <summary>
            /// 名称:CheckChildOpenState
            /// 功能:用子窗体的Name进行判断是否已实例化,如果存在则将他激活
            /// </summary>
            /// <param name="MdiForm">容器窗体</param>
            /// <param name="ChildForm">子窗体</param>
            public static void CheckChildOpenState(Form MdiForm, Form ChildForm)
            {
                foreach (Form tempChildForm in MdiForm.MdiChildren)
                {
                    if (tempChildForm.Name == ChildForm.Name.ToString())
                    {
                        if (tempChildForm.WindowState == FormWindowState.Minimized)
                        {
                            tempChildForm.WindowState = FormWindowState.Normal;
                        }
                        tempChildForm.Activate();
                        return;
                    }
                }
                ChildForm.MdiParent = MdiForm;
                ChildForm.Show();
            }
            #endregion
      

  2.   

    谢谢楼上的回复,我的问题不是这样的
    主窗体上有很多按钮,“首页”按钮对应着主窗体的显示,其他按钮分别对应各个子窗体。
    点击某个子窗体的按钮,即Load某个子窗体并显示它。
    点击首页按钮,则关闭所有子窗体,并显示主窗体。我现在遇到的问题是:在首页按钮的事件中,把所有的子窗体都CLose了。
    然后点击某个子窗体按钮时,执行if (FORM2 == null) 语句,判断该子窗体是否为null,按道理前面CLose了,这里应该是null,但是我这里的代码执行判断为false,FORM2不为null。如果在VB6里面,可以在FORM2的Close事件里:set form2 = nothing。
    C#里面好像不能这么写,所以想问问,应该怎么写?
      

  3.   

    上面的方法你变通一下,单独加个判断即可。如:给方法加个参数,来判断是否是单击的首页按钮,如true:关闭所有的子窗体,false:执行方法体即可。public static void CheckChildOpenState(Form MdiForm, Form ChildForm)
            {
                if(false)            foreach (Form tempChildForm in MdiForm.MdiChildren)
                {
                    if (tempChildForm.Name == ChildForm.Name.ToString())
                    {
                        if (tempChildForm.WindowState == FormWindowState.Minimized)
                        {
                            tempChildForm.WindowState = FormWindowState.Normal;
                        }
                        tempChildForm.Activate();
                        return;
                    }
                }
                ChildForm.MdiParent = MdiForm;
                ChildForm.Show();
                else{关闭所有子窗体}        }
      

  4.   

    嗯,谢谢,我再问个问题:
    我希望执行这么一条语句:ChildForm = null;
    这条语句应该不能像VB那样,直接写在 ChildForm的close事件中吧?是不是也没法写在ChildForm里面呢?如果不能写在ChildForm里面,那么是不是需要通过委托的方式,写在主窗体里面呢?
      

  5.   

    找到答案了,同时也谢谢楼上的朋友的帮助,我把答案贴这里,希望对大家有帮助:
    如果不用MDI来实现一个主窗体打开多个子窗体时,
      从一个窗体(主窗体)打开一个(only one) 另外一个的窗体(子窗体)的实现
      父窗体:MainForm
      public partial class MainForm:Form
      {
       ............
       private void menuItem1_Load(object sender,EventArgs e) 
       {
       ChildForm child1=ChildForm.Create();
       child1.show();
       child1.Focus();
       }
       
       //......
      }
      子窗体:ChildForm
      public partial class ChildForm:Form
      {
       .....
       static ChildForm child;
       
       Public static ChildForm Create()
       {
       if(child==null)
       child=new ChildForm();
       return Child; 
       }
       ......
      }
      F5运行后,的确实现了上面提到的功能。然而,把子窗体关闭后,想再次打开该子窗体时,单击菜单项,会出现异常:ObjectDisposedException was unhandled.
       这是为什么呢??
      这里涉及到C#垃圾回收的问题:
      垃圾回收是.NET运行库的一部分。垃圾回收器管理所有的托管对象,所有需要托管数据的.NET语言(包括 C#)都受运行库的垃圾回收器的制约。垃圾回收器可以确定运行垃圾回收的最佳时间,自动进行垃圾回收。然而垃圾回收的一个产物是:C# 对象没有确定性毁坏。所以会出现对象child已被销毁,但又不为null,访问时产生ObjectDisposedException异常。
       怎么办??
       方法:应该彻底回收Child所占的资源。
       途径有二: 
      方法一:
      修改子窗体的构造函数
      public ChildForm()
      {
       //.........
       this.Disposed+=new System.EventHandler(Form_Disposed)
      }
      然后事件Form_Disposed的处理函数
      private void Form_Disposed(object sender,EventArgs e)
      {
       Child=null;
      }
      方法二:
      重写ChildForm的OnClosed方法
      Protected void OnClosed(EventArgs e)
      {
       base.OnClosed(e); 
       child=null;
      }
      当然可能有其他的方法,各位看客有兴趣的话补充一下。另外有叙述不当的地方,请多多指教,在下感激不尽。