关于c#:Foreach循环,用于处理跳过迭代的控件

Foreach loop for disposing controls skipping iterations

创建文本框的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
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);              
}

删除所有文本框的代码。

ZZU1

当我点击BTNADDREMENT时,我得到了希望的跟踪。MGX1〔0〕

但当我点击复位时,它错过了第二个文本框。See below…

MGX1〔1〕

我不知道这是怎么回事,但这是同一件事,无论我是如何增加拳击手。每次都会错过第二个盒子。


您应该使用逆向标准for循环来处理其容器中的SmartTextBox。

1
2
3
4
5
6
7
8
9
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();
    }
}

根据这个问题/答案,您不需要将它们从容器中移除,当然这避免了两个循环(显式或隐式)。同样,在接受的答案中,您可以看到代码每两个跳转一个控件的原因。

1
2
3
4
if (parent != null)
{
    parent.Controls.Remove(this);
}

要释放的控件将从正在迭代的集合中删除。(不清楚为什么这不会引发标准异常)。

相反,使用简单的for-in-reverse循环可以避免对要处理的控件的有序访问中出现任何问题。


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

1
2
3
4
foreach (Control c in this.Controls.ToArray())
{
    ...
}


删除代码不正确,因为您通过调用Dispose()来修改Controls集合,这就是为什么您可以跳过控件。

删除特定类型的选项最简单的方法是执行以下操作:

1
2
var smartTbs = this.Controls.OfType<BnBCalculator.SmartTextBox>().ToList();
smartTbs.ForEach(x => x.Dispose());

您必须先从窗体中移除控件。控件,然后将其丢弃。

1
2
3
4
5
6
7
8
9
10
11
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);
}

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

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