1

我在 Windows 窗体应用程序中有一个方法,它试图从面板中删除 2 个文本框。

在该方法中,我遍历面板中的所有控件。总是应该有 2 个面板被移除并添加在一起,但是在移除时,当我按下按钮时它会随机移除 1 或 2 个容器。

这是删除文本框的代码:

private void removeRows()
        {
            string descName = "Desc" + (textBoxCounter - 1).ToString();
            string costName = "Cost" + (textBoxCounter - 1).ToString();

            if (textBoxCounter >= 0)
            {
                foreach (Control c in costItems.Controls)
                {
                    if (c.Name == descName)
                    {
                        // Remove the control from the panel and dispose of it
                        panel.Controls.Remove(c);
                        c.Dispose();

                    }
                    if(c.Name == costName)
                    {
                        // Remove the control from the panel and dispose of it
                        panel.Controls.Remove(c);
                        c.Dispose();
                    }
                }

                // Decrement the counter
                // This happens only once since two controls need to be removed
                if (textBoxCounter == 0)
                    textBoxCounter = 0;
                else
                    textBoxCounter--;
            }
            else
                MessageBox.Show("There are no more rows to remove", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

            testlabel1.Text = textBoxCounter.ToString();
            testlabel2.Text = panel.Controls.Count.ToString();
        }

这是添加按钮的代码:

private void addRows(string desc, string cost)
    {
        if (textBoxCounter >= maxExpenses)
        {
            MessageBox.Show("Maximum number of expenses entered", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        else
        {
            TextBox Desc = new TextBox();
            TextBox Cost = new TextBox();

            // Give the text boxes names
            Desc.Name = "Desc" + textBoxCounter.ToString();
            Cost.Name = "Cost" + textBoxCounter.ToString();

            // Format the text boxes
            Desc.Width = panel.Width / 2;
            Cost.Width = panel.Width / 4;

            // Add the items to the costItems panel
            panel.Controls.Add(expenseDesc);
            panel.Controls.Add(expenseCost);

            // Add the items to the expenses dictionary
            panel.Add(Desc, Cost);

            // Increment the text box counter variable
            textBoxCounter++;
            testlabel1.Text = textBoxCounter.ToString();
            testlabel2.Text = costItems.Controls.Count.ToString();
        }
    }

一些信息要知道。总是会添加和删除 2 个文本框,它们相互关联。textBoxCounter 初始化为 0,因此前两个框名称将是“Desc0”和“Cost0”。

当我第一次按下按钮删除行时,一个文本框被删除,然后如果我再次按下它可能会删除 2,它可能只删除 1。

我尝试调试,我注意到迭代面板中所有控件的 foreach 循环似乎比全部控件数量少循环一次。

对我的代码有任何帮助都会很棒。

4

2 回答 2

1

您的问题是由 引起的,在foreach中修改集合foreach可能会导致一些意外行为。您只想删除TextBoxes 预先知道的名称,那么为什么不使用该方法ControlCollection.RemoveByKey呢?

如果要删除最后添加的文本框(Desc...Cost...),请执行以下操作:

panel.Controls.RemoveByKey(descName);
panel.Controls.RemoveByKey(costName);

如果要删除所有添加的文本框(假设您有其他类型的TextBoxes,否则我们可以使用一点LINQ来轻松删除所有文本框):

for(int i = 0; i < textBoxCounter; i++){
   panel.Controls.RemoveByKey("Desc" + i);
   panel.Controls.RemoveByKey("Cost" + i);
}
于 2013-09-16T18:11:45.437 回答
1

您的代码有两个问题:您正在处理您无法处理的东西,并且您正在以错误的方式迭代一个集合(您正在修改它)。您可以通过以下方式删除所有Controls内容:

panel.Controls.Clear();

或者通过依赖索引向后迭代:

for (int i = panel.Controls.Count - 1; i >= 0; i--)
{
    panel.Controls.RemoveAt(i);
}

关于 Dispose,您可以根据需要使用它,但不需要使用 Remove:

for (int i = panel.Controls.Count - 1; i >= 0; i--)
{
    panel.Controls[i].Dispose();
}

PS:我问了与此相同的问题并得到-6。维护这个问题的原因之一就是对其他人有帮助(我看到了你用来删除互联网上的控件的代码,我知道有很多人在使用它)。确实很讽刺。

于 2013-09-16T18:19:26.193 回答