none
子表單重覆開啟的問題 RRS feed

  • 問題

  •  

    在點選menuItem的時候,會在MDI父表單之中,開出所對應的子表單,這一點目前沒有問題。

    但若是按子表單右上方的╳關閉,再次點擊同一個menuItem,就會出現一項錯誤訊息:

     

    ObjectDisposedException未處理
    嘗試使用資源之前,先確定您尚未釋放該資源。
    例如,嘗試操作資料流時,請確定先前未關閉該資料流。


    在下認為╳關閉之後,子表單已經dispose。

    試想使用者可能會重覆點選同一個menuItem,所以子表單應該不能被釋放(Hide)

    呃…想歸想,但還是不會寫這段,有勞各位專家指導。

     

    在下接觸C sharp的時間不長

    想請教如何使各子表單經過關閉的動作之後,點擊menuItem時又能再次開啟

     

    程式碼區塊

        //MDI父表單程式片斷

        partial class MainForm : System.Windows.Forms.Form
        {
            private System.Windows.Forms.MenuStrip menuStrip1;
            private System.Windows.Forms.ToolStripMenuItem menuView;
            private System.Windows.Forms.ToolStripMenuItem itemA, itemB;
            private FormA frmA;
            private FormB frmB;

            /*中間省略

             *...

             **/

            private void MainForm_Load(object sender, EventArgs e)
            {
                frmA = new FormA();
                frmB = new FormB();
            }

            private void itemA_Click(object sender, EventArgs e)
            {
                frmA.MdiParent = this;
                frmA.Show();
            }
            private void itemB_Click(object sender, EventArgs e)
            {
                frmB.MdiParent = this;
                frmB.Show();
            }
        }

     

     

    2007年10月25日 下午 06:52

解答

  •  partial class MainForm : System.Windows.Forms.Form
        {
            private System.Windows.Forms.MenuStrip menuStrip1;
            private System.Windows.Forms.ToolStripMenuItem menuView;
            private System.Windows.Forms.ToolStripMenuItem itemA, itemB;
            private FormA frmA;
            private FormB frmB;

            /*中間省略

             *...

             **/

            private void MainForm_Load(object sender, EventArgs e)
            {
                frmA = new FormA();
                frmB = new FormB();
            }

            private void itemA_Click(object sender, EventArgs e)
            {
                frmA.MdiParent = this;
                frmA.Show();
            }
            private void itemB_Click(object sender, EventArgs e)
            {
                frmB.MdiParent = this;
                frmB.Show();
            }
        }

     

     

    你確定你的Form 有被Dispose 嗎?

    你這樣做變成全域變數,就算Closed掉也不一定被Dispose一掉.

    而且你這裡只有FormA,跟FormB,如果像一支像ERP的程式最少上百個Form,光是你MainForm_Load就當在那裡.

    所以改成

    partial class MainForm : System.Windows.Forms.Form
        {
            private System.Windows.Forms.MenuStrip menuStrip1;
            private System.Windows.Forms.ToolStripMenuItem menuView;
            private System.Windows.Forms.ToolStripMenuItem itemA, itemB;
            private FormA frmA;
            private FormB frmB;

            /*中間省略

             *...

             **/

            private void MainForm_Load(object sender, EventArgs e)
            {
            }

            private void itemA_Click(object sender, EventArgs e)
            {

                if(frmA==null){

                   frmA=new FormA();
                frmA.MdiParent = this;

                 }
                frmA.Show();
            }
            private void itemB_Click(object sender, EventArgs e)
            {

                if(frmB==null){

                   frmB=new FormB();
                frmB.MdiParent = this;

                }
                frmB.Show();
            }
        }

     

    Form 要用到時在去New,先判斷該Form有沒有在用,如果有就不用New,如果第一次用Or上次用過後被Dispose掉,就在New一個.

    另外比如User只使用FormA的功能,就不會去New FormB 去浪費系統資源.

    2007年10月26日 上午 09:01

所有回覆

  • HI  瞇 Sir :

     

    下面程式碼 給你參考  ︿︿

     

    程式碼區塊

     

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;

    namespace WindowsApplication1
    {
        public partial class Form1 : Form
        {

          

            FormA FormA ;
            FormB FormB ;

     

            public Form1()
            {
                InitializeComponent();

     

                Form2 FormA = new FormA();
                Form2 FormB = new FormB();

     

              FormA.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.FormA_FormClosed);

     

                FormB.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.FormB_FormClosed);


            
            }

     

            private void FormA_FormClosed(object sender, FormClosedEventArgs e)
            {
                FormA = null; 
            }


            private void FormB_FormClosed(object sender, FormClosedEventArgs e)
            {
                FormB = null;
            }

     


            private void item1ToolStripMenuItem_Click(object sender, EventArgs e)
            {
                if (FormA == null)
                {
                    FormA = new FormA();
                    FormA.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.FormA_FormClosed);

                }

     

                FormA.MdiParent = this;
                FormA.Show();


            }

            private void item2ToolStripMenuItem_Click(object sender, EventArgs e)
            {
                if (FormB == null)
                {
                    FormB = new FormB();
                    FormB.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.FormB_FormClosed);

                }

                FormB.MdiParent = this;
                FormB.Show();

            }
        }
    }

     

     

    2007年10月26日 上午 01:20
  • 如果只是為了避免MDIChild重覆開啟同一個MDIChild,我的做法如下:

    程式碼區塊

     private void newFormToolStripMenuItem_Click(object sender, EventArgs e)
     {
          Form[] a=this.MdiChildren;//取得所有的MdiChild
          foreach (Form b in a)
          {
              if (b.Name.ToUpper().Trim() == "FORM5")//判斷Form5是否已被開啟
              {
                  MessageBox.Show("表單已開啟");
                  return;//跳出,不接著執行下去
              }
          }
          Form5 obj = new Form5();//開啟表單
          obj.MdiParent = this;
          obj.Show();            
    }

     

     

    我只有在Item_Click事件去判斷,其它的MDI Child沒去動.

    2007年10月26日 上午 07:23
  •  partial class MainForm : System.Windows.Forms.Form
        {
            private System.Windows.Forms.MenuStrip menuStrip1;
            private System.Windows.Forms.ToolStripMenuItem menuView;
            private System.Windows.Forms.ToolStripMenuItem itemA, itemB;
            private FormA frmA;
            private FormB frmB;

            /*中間省略

             *...

             **/

            private void MainForm_Load(object sender, EventArgs e)
            {
                frmA = new FormA();
                frmB = new FormB();
            }

            private void itemA_Click(object sender, EventArgs e)
            {
                frmA.MdiParent = this;
                frmA.Show();
            }
            private void itemB_Click(object sender, EventArgs e)
            {
                frmB.MdiParent = this;
                frmB.Show();
            }
        }

     

     

    你確定你的Form 有被Dispose 嗎?

    你這樣做變成全域變數,就算Closed掉也不一定被Dispose一掉.

    而且你這裡只有FormA,跟FormB,如果像一支像ERP的程式最少上百個Form,光是你MainForm_Load就當在那裡.

    所以改成

    partial class MainForm : System.Windows.Forms.Form
        {
            private System.Windows.Forms.MenuStrip menuStrip1;
            private System.Windows.Forms.ToolStripMenuItem menuView;
            private System.Windows.Forms.ToolStripMenuItem itemA, itemB;
            private FormA frmA;
            private FormB frmB;

            /*中間省略

             *...

             **/

            private void MainForm_Load(object sender, EventArgs e)
            {
            }

            private void itemA_Click(object sender, EventArgs e)
            {

                if(frmA==null){

                   frmA=new FormA();
                frmA.MdiParent = this;

                 }
                frmA.Show();
            }
            private void itemB_Click(object sender, EventArgs e)
            {

                if(frmB==null){

                   frmB=new FormB();
                frmB.MdiParent = this;

                }
                frmB.Show();
            }
        }

     

    Form 要用到時在去New,先判斷該Form有沒有在用,如果有就不用New,如果第一次用Or上次用過後被Dispose掉,就在New一個.

    另外比如User只使用FormA的功能,就不會去New FormB 去浪費系統資源.

    2007年10月26日 上午 09:01
  • 原來如此 

     

    恩…我的觀念不大清楚。

     

    我會再修改看看,有問題再上來請教您。

     

    且謝謝以上各位的指導。

    2007年10月26日 下午 03:17
  • 修改出來了,問題是在於本身所寫的new,如您所言根本不需要放到Load,在下真是多此一舉了。

     

    但是您給的意見是我都沒想過的重點,不甚感激。

    2007年10月26日 下午 04:17