2

foreach在按钮单击事件处理程序中有一个循环,我用它来摆脱所有位于 Y 轴上同一点的控件。我有一个添加一行的控件,然后我需要用户可以选择删除他们不想添加的行。

当我单独使用foreach循环时,它总是会遗漏两项——每次都是相同的两项。我已经确认 Y 值实际上是相同的。如果我继续运行该函数,它会在运行三次后删除该行上的所有控件。但是,如果我使用所有相同的值嵌套foreach循环,它就可以工作。请参阅下面的代码。

这似乎是一种非常草率的方法,但它也是唯一对我有用的解决方案。我看到其他几个帖子说要在循环中声明第二个变量(即Control z = c; if(z.Location....))。这对这里的行为没有任何影响。谁能解释为什么foreach循环本身不起作用?如何在没有重复嵌套的情况下修复它?

在职的:

    internal void MinButt_Click(object sender, EventArgs e)
    {
        Scratch.tScratch.panel2.Controls.RemoveByKey("Record" + arrDynamY[0].ToString());
        foreach (Control c in Scratch.tScratch.panel2.Controls)
        {
            if (c.Location.Y == arrDynamY[1])
            {
                c.Dispose();
            }

            foreach (Control ctrl in Scratch.tScratch.panel2.Controls)
            {
                if (ctrl.Location.Y == arrDynamY[1])
                {
                    ctrl.Dispose();
                }
            }
        }
    }

每次都错过相同的两个控件:

    internal void MinButt_Click(object sender, EventArgs e)
    {
        Scratch.tScratch.panel2.Controls.RemoveByKey("Record" + arrDynamY[0].ToString());
        foreach (Control c in Scratch.tScratch.panel2.Controls)
        {
            if (c.Location.Y == arrDynamY[1])
            {
                c.Dispose();
            }
        }
    }
4

4 回答 4

3

您应该首先获得用于删除和删除它们的控件,如下所示:

var controlsToRemove = from Control c in Scratch.tScratch.panel2.Controls
                       where c.Location.Y == arrDynamY[1]
                       select c;

foreach (var c in controlsToRemove.ToArray())
{
    Scratch.tScratch.panel2.Controls.Remove(c);
    c.Dispose();
}
于 2013-02-20T06:52:57.690 回答
1

您正在修改(在这种情况下处理)您正在迭代的集合的项目,我相信这就是导致意外行为的原因,您可以使用for循环来避免此问题:

        for (int i = Scratch.tScratch.panel2.Controls.Length - 1; i >= 0; i-- )
            if (Scratch.tScratch.panel2.Controls[i].Location.Y == arrDynamY[1])
                Scratch.tScratch.panel2.Controls[i].Dispose();

我假设Scratch.tScratch.panel2.Controls可以作为数组访问。

于 2013-02-20T06:52:28.290 回答
0

也许在单独的循环中进行处理,它可能会影响其他控件

试试这个

internal void MinButt_Click(object sender, EventArgs e)
{
    Scratch.tScratch.panel2.Controls.RemoveByKey("Record" + arrDynamY[0].ToString());
    var controlsToDispose = new List<Control>();
    foreach (Control c in Scratch.tScratch.panel2.Controls)
    {
        if (c.Location.Y == arrDynamY[1])
        {
            controlsToDispose.Add(c);
        }
    }
    foreach (Control c in controlsToDispose )
    {
        c.Dispose();
    }              
}
于 2013-02-20T06:47:16.370 回答
-1

这是因为当您在控件上调用 Dispose() 时,它只会在 GC 启动之前保留在内存中。请尝试以下操作。

List<Control> controlsToDispose = new List<Control>();
foreach (Control c in Scratch.tScratch.panel2.Controls)
{
       if (c.Location.Y == arrDynamY[1])
       {
           controlsToDispose.Add(c);
           c.Dispose();
       }
}
while(controlsToDispose.Count>0)
{
      Control ctrl = controlsToDispose[0];
      controlsToDispose.RemoveAt(0);
      ctrl.Dispose();
}
于 2013-02-20T06:59:08.477 回答