none
在runtime時如何取得自Form.Controls移除(remove)後的Control RRS feed

  • 問題

  • Hi! Everyone,

    先交待一下環境....

    (1) Visual Studio 2005 Professional, CHT
    (2) C#, WinForm
    (3) Form上有2個Private的Button

    問題是這樣子的,當我將其中Button1從Form的Controls中以Remove方法將其移除,如此在Controls這個集中便找不到Button1,然而Button1仍存在於記憶體中(因為沒有Dispose),想請教,此時是否能夠透過Button1的名稱(String)從記憶體中找回並再加回Controls集合??

    ex.

    1. Control ctrl = SomeObject.Find("name");
    2. Controls.Add(ctrl);

    Please help me....^^

    Best regards,
    huangchin, 2006/03/20

    2006年3月20日 下午 01:50

解答

  • 應該可以, 你可以先開一個C#的Windows Application專案, 然後分別拉三個Button與一個Panel到Form上頭, 將下面是Form1.cs的內容, 然後按F5執行, 你應該可以在Runtime時Remove與Add同一個Control

    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
       
    {
            public Form1()
            {
                InitializeComponent();
            }

            private void button1_Click(object sender, EventArgs e)
            {
                if (panel1.Controls.Contains(TestButton))
                {
                    panel1.Controls.Remove(TestButton);
                }
            }

            private void button2_Click(object sender, EventArgs e)
            {
                if (!panel1.Controls.Contains(TestButton))
                {
                    panel1.Controls.Add(TestButton);
                }
            }
        }
    }

    2006年3月20日 下午 05:07
  • Dear huangchin:

    我想應該是不行的,雖然btn還是存在記憶體中,但是在程式主體的環境下已經不存在了,它已經算是GC的管轄範圍內了。

    這樣說好了,物件的生命週期依存在Process或Thread的管轄內,如果不在這裡面,那就歸GC管轄。所以如果只是單純Form上面的一個Control,當他從Form這個Container被移除後,Process或Thread本身對這個物件沒有任何指涉的話,那它應該就歸GC管理,一般來說是沒辦法取得這個物件。也就是說,合理的GC應會在程式要強制指涉這個廢棄的物件時發出錯誤。但是當物件有任何存在的跡象時,或是指標的指向時,那就不會進入GC的世代裡。

    所以基本上,我會覺得你把型別(Type)保留下來,到時候再New會比較實在。

    這是我的想法啦!歡迎大家來討論喔!

    2006年3月28日 上午 05:35

所有回覆

  • 應該可以, 你可以先開一個C#的Windows Application專案, 然後分別拉三個Button與一個Panel到Form上頭, 將下面是Form1.cs的內容, 然後按F5執行, 你應該可以在Runtime時Remove與Add同一個Control

    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
       
    {
            public Form1()
            {
                InitializeComponent();
            }

            private void button1_Click(object sender, EventArgs e)
            {
                if (panel1.Controls.Contains(TestButton))
                {
                    panel1.Controls.Remove(TestButton);
                }
            }

            private void button2_Click(object sender, EventArgs e)
            {
                if (!panel1.Controls.Contains(TestButton))
                {
                    panel1.Controls.Add(TestButton);
                }
            }
        }
    }

    2006年3月20日 下午 05:07
  • Thanks for your answer, Peter.

    這個方式的確可行,因為TestButton還是一個存在於記憶體的實體,事實上這個方式已經在提出此問題前試驗過,我想應該是我的問題表達的不夠完整,在問題的描述最下方有提及預想中的2行程式碼,意思即是我是已知TestButton的Name屬性值(假定是"TestButton"),而我要利用這個已知的字串在記憶體中來找到這個已存在的實體,然後再將其重新加入Controls集合,甚至是當我找不到這的實體的前提下,重新New出一個實體.

    1. Button btn = (Button)SomeObj.SomeMethod("button1");
    2. Controls.Add(btn);

    Best regards,
    huangchin, 2006/03/21

    2006年3月21日 上午 01:11
  • Dear huangchin:

    我想應該是不行的,雖然btn還是存在記憶體中,但是在程式主體的環境下已經不存在了,它已經算是GC的管轄範圍內了。

    這樣說好了,物件的生命週期依存在Process或Thread的管轄內,如果不在這裡面,那就歸GC管轄。所以如果只是單純Form上面的一個Control,當他從Form這個Container被移除後,Process或Thread本身對這個物件沒有任何指涉的話,那它應該就歸GC管理,一般來說是沒辦法取得這個物件。也就是說,合理的GC應會在程式要強制指涉這個廢棄的物件時發出錯誤。但是當物件有任何存在的跡象時,或是指標的指向時,那就不會進入GC的世代裡。

    所以基本上,我會覺得你把型別(Type)保留下來,到時候再New會比較實在。

    這是我的想法啦!歡迎大家來討論喔!

    2006年3月28日 上午 05:35