使用foreach循环释放控件时如何跳过迭代。

6

创建文本框的代码...

private void btnAddIncrement_Click(object sender, EventArgs e)
{              
    SmartTextBox dynamictextbox = new SmartTextBox();

        dynamictextbox.BackColor = Color.Bisque;
        dynamictextbox.Width = this.tbWidth;
        dynamictextbox.Left = (sender as Button).Right + this.lastLeft;
    dynamictextbox.K = "Test";

    this.lastLeft = this.lastLeft + this.tbWidth;
    dynamictextbox.Top = btnAddStart.Top;
    this.Controls.Add(dynamictextbox);              
}

删除所有文本框的代码。

foreach (Control c in this.Controls)
{

    if (c.GetType() == typeof(BnBCalculator.SmartTextBox))
    {
        count++;
        //MessageBox.Show((c as SmartTextBox).K.ToString());
        c.Dispose();
    }
   // else { MessageBox.Show("not txtbox"); }

}

当我点击btnAddIncrement时,如预期所示,会出现以下内容... enter image description here 但是当我点击重置按钮时,它会错过每个第二个文本框。如下图所示... enter image description here 不知道发生了什么,但无论我添加多少文本框都是一样的。它总是漏掉每第二个框。

可能是foreach控件c#跳过控件的重复问题。 - Lance U. Matthews
5个回答

8
你应该使用一个反向标准循环来处理 SmartTextBoxes 容器中的元素。
for(int x = this.Controls.Count - 1; x >= 0; x--)
{
    BnBCalculator.SmartTextBox c = this.Controls[x] as BnBCalculator.SmartTextBox;
    if (c != null)
    {
        count++;
        c.Dispose();
    }
}

根据这个问题/答案,您不需要从容器中删除它们,这当然避免了两个循环(显式或隐式)。此外,在接受的答案中,您可以看到为什么您的代码每两个跳过一个控件。
if (parent != null) 
{ 
    parent.Controls.Remove(this); 
}

您要处理的控件已从您正在迭代的集合中移除。(不清楚为什么这不会抛出标准异常)。相反,通过简单地反向使用for循环避免任何有序访问控件以进行处理的问题。

2
你的移除代码有误,因为你调用了 Dispose() 方法修改了 Controls 集合,这就是你跳过控件的原因。
移除特定类型控件的最简单方法如下:
var smartTbs = this.Controls.OfType<BnBCalculator.SmartTextBox>().ToList();
smartTbs.ForEach(x => x.Dispose());

2

当你从this.Controls移除一个项目时,集合会被修改,因此下一个项目不是你所期望的。你应该将this.Controls复制到一个新列表中。例如,你可以使用ToArray来复制this.Controls

foreach (Control c in this.Controls.ToArray())
{
    ...
}

1
首先,您需要从Form.Controls中删除控件,然后再进行处理。
var controlsToRemove = new List<Control>();
foreach (Control c in this.Controls)
{
    if (c is BnBCalculator.SmartTextBox) 
        controlsToRemove.Add(c);
}

foreach (Control c in controlsToRemove)
{
    Controls.Remove(c);
}

0

尝试先选择所有的SmartTextBox控件,然后在另一个循环中将它们释放。伪代码:

    SmartTextBoxes = Select From this.Controls Where (c.GetType() == typeof(BnBCalculator.SmartTextBox));
    foreach(stb in SmartTextBoxes) { stb.Dispose(); }

1
дҢ еЏҮд»ӨдҢүз”ЁLINQзљ„OfType<T>()ж–№жі•гЂ‚ - toadflakz
没错。但是在IDE之外编写正确的LINQ表达式有点困难。因此,我只是根据LINQ编写了“伪代码”。 - MobileX

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接