我在一个form窗体上添加了一个Panel控件,在Panel上添加了四个控件,在panel外的窗体上添加了一个button控件。我想实现点击button按钮panel上的控件就消失。我在Pannel控件里写了个这样的语句
private void button1_Click(object sender, EventArgs e)
{
foreach (Control c in this.panel1.Controls)
{
c.Dispose();
}
}
但是是,实际运行效果是点击button之后只要两个控件消失了,再点击又消失两个。我不明白为什么。是语句写错了吗?我想知道这个语句哪出错了。

解决方案 »

  1.   

    private void button1_Click(object sender, EventArgs e)
    {
    foreach (Control c in this.panel1.Controls)
    {
    c.Visible=false;
    }
    }
      

  2.   

    private void button1_Click(object sender, EventArgs e)
    {
    foreach (Control c in this.panel1.Controls)
    {
    c.Visable=false;
    }
    }或者private void button1_Click(object sender, EventArgs e)
    {
    int count=this.panel1.Controls.Count;
    for(int i=count-1;i>=0;i--)
    {
    Control c = this.panel1.Controls[0];
    c.Visable=false;
    }
    }
      

  3.   

    更正一下:
    private void button1_Click(object sender, EventArgs e)
    {
    foreach (Control c in this.panel1.Controls)
    {
    c.Hide();
    }
    }
      

  4.   

    这样写运行时没直接报错已经是面子事了,因为你在foreach循环中改变了Controls的大小,而这是不允许的.
      

  5.   

    我刚才看了下,其实没区别,一样的。Hide()方法内部就是Visible=false;
      

  6.   


    我不太明白。怎么改变了Controls的大小。能详细解释下吗?我刚开始学C#。。这个问题我百度了好久也没百度 出来
      

  7.   

    你要先获取panel中所有的子控件,再设置显示属性
      

  8.   

    这个我明白。想问的是foreach遍历不了Panel的子控件吗?
      

  9.   


    我也不明白Control.Dispose中都干了些什么事,导致Controls大小的变化,不过从以下试验可以得出结论:
     while (this.panel1.Controls.Count > 0)
                {
                    this.panel1.Controls[0].Dispose();
                    MessageBox.Show(this.panel1.Controls.Count.ToString());//报出的值越来越小
                }
      

  10.   


    调用dispose方法之后控件直接释放,也就是说panel的子控见总数自然你就少了。这个问题应该出在foreach语句遍历这个集合的问题上面具体什么问题就只能期待大神回答了。。
      

  11.   

    那你认为Controls中的任何一项只要Dispose后,Controls的数目变少是合理的吗?
      

  12.   


    嗯。我就是这么认为的。dispose方法是释放一个控件占有的所有资源。就是说这个控件彻底消失了。和Hide方法是不一样的。
      

  13.   

    foreach循环过程中是绝对不可以删减被枚举对象(也就是本例中的Controls)的成员的,因为有的IEnumerator是通过元素在集合中的位置下标来确定MoveNext方法的执行和Current的,改变集合的大小会影响到每一个成员在集合位置中的下标,比如你删掉了0,导致原来的1的下标变为0,2的下标变为1,本来MoveNext应该取1时,实际上取到的是原来的2,这样1就被漏掉了.基于链表的集合同样存在这样的问题,因为当前元素被移出,MoveNext后,会被直接移到null上,导致异常.对于foreach的实现,可以参看MSDN中对于IEnumerable的解释.
      

  14.   

    Dispose不会从集合中删除control吧?
      

  15.   


    这个真会,我试过了,查了查IL,内容太多,没找到.Net是在哪个位置实现的
      

  16.   

    我们自己在写类似于这样的类时,也会纠结于Parent和Children集合对接的完美实现(自己实现的总是漏洞太多,给别人用很难防止出现BUG),想和系统学一学,结果没找到.
      

  17.   

    就在Control.Dispose(boolean)里
                    if (this.parent != null)
                    {
                        this.parent.Controls.Remove(this);
                    }
    还有一个比较诡异的问题。微软提供的源码中,ControlCollection的枚举器是做了集合改变检查的,检查到集合改变了也抛出了异常来中断枚举。
    但实际上发行的.NET程序集里面又没有检查集合的更改。而且那个代码也比较奇怪,似乎暗示了它知道在迭代过程中集合会被改变(所以检查了this.controls.Count)
    public bool MoveNext()
    {
        if ((this.current < (this.controls.Count - 1)) && (this.current < (this.originalCount - 1)))
        {
            this.current++;
            return true;
        }
        return false;
    }
    莫非是因为某种原因故意这么实现的
      

  18.   

    我也觉得dispose不会改变 controls的大小 
    虽然dispose掉了 只是把这个资源释放掉了 这个变量名却还是存在的
    就像
    Form frm = new Form();
    frm.Name = "Test";
    frm.Show();
    frm.Dispose();
    MessageBox(frm.Name);
    虽然被dispose掉了 但是还是可以访问frm对象 直到frm的生命周期结束
    如果 用remove的话 那么就会影响controls的大小了、、
    好吧 我只是过来打酱油的、、、
      

  19.   

    遍历controls还是不得已而为之吧,如果都是你自己写的,你大可建立个容器,去foreach自己的容器这样各个方面都有好处。