2014-03-29 84 views
1

我在Microsoft Visual Studio 2012中使用C#。 我有一个程序在其中创建一组按钮,所有都被分配了相同的事件处理程序。 (花哨的方式让用户选择一个选项。)一旦选择了这个选项,我需要销毁所有这些按钮。我一直在使用下面的代码:C#一次删除多个按钮

foreach (Control c in this.Controls) 
{ 
    if (c.GetType() == typeof(Button)) 
    { 
     c.Click -= new EventHandler(TeamChoiceButton_Click); 
     this.Controls.Remove(c); 
     c.Dispose(); 
    } 
} 

问题是它是删除其他每个按钮。我假设,因为我在foreach中删除了它们,所以它调整了索引,使其跳过其他所有索引。什么是正确的方法来做到这一点?任何帮助将不胜感激,特别是如果我误解为什么它跳过其他按钮。

+1

将它们放在面板和迭代'panel.Controls' – etaiso

+1

使用'for'索引到列表和重复最后一个到第零个。 –

+0

当你说'每个其他按钮',你是说它正在删除你不想删除的按钮,或者它只是删除了一半的按钮? –

回答

2

你可以把所有你快速进入List<Button>创建按钮,当您创建 然后使用:

foreach (Button b in myButtonList) 
{ 
    this.Controls.Remove(b); 
} 
myButtonList.Clear(); 
4

值的按钮的Tag属性添加,以纪念他们为稍后删除。

var btn = new Button(); 
btn.Tag = new object(); 
btn.Text = "xy"; 
... 
this.Control.Add(btn); 

然后你可以将其删除:

var myButtons = this.Controls 
    .OfType<Button>() 
    .Where(b => b.Tag != null) 
    .ToList(); //Because you cannot modify the collection being iterated with for each. 
foreach (Button b in myButtons) { 
    b.Click -= new EventHandler(TeamChoiceButton_Click); 
    this.Controls.Remove(b); 
    b.Dispose(); 
} 

LINQ到对象查询的懒惰的方式执行。这意味着如果我们不在查询中添加.ToList(),则查询会按照foreach循环进行评估。枚举Controls集合时删除Controls集合中的控件将引发异常。 .ToList()强制过早评估查询,从而消除该问题。

+0

我最终使用了列表后面的迭代,但是我想喜欢解释上面的代码,看看我是否理解它。 myButtons var是this.Controls的引用变量。和各种.OfType和.Where Linq函数来操纵列表。 .ToList将其从任何类型的控件(IEnumerable?)更改为实际的IList类型。由于我遍历引用变量,所以如果我更改数据变量this,它的索引不会改变。控件 –

+0

'OfType ()'和'Where(...)'是应用于枚举控件的过滤器。 'Controls'属性。如果没有'ToList()''myButtons'变量只会是一个无用的查询,直到'foreach'语句执行查询。使用'ToList()'调用立即执行查询,'myButtons'变成'List

3

您可以通过列表向后迭代和删除的项目那样:

for (int i = this.Controls.Count - 1; i >= 0; i--) 
{ 
    Control c = this.Controls[i]; 
    if (c.GetType() == typeof (Button)) 
    { 
     c.Click -= new EventHandler(TeamChoiceButton_Click); 
     this.Controls.RemoveAt(i); 
     c.Dispose(); 
    } 
} 
+0

感谢这工作完全根据需要(也感谢安德鲁莫顿相同的答案)。 –