C# 如何遍历删除某个控件上的所有子控件

本文探讨了在C#中使用Dispose方法批量移除窗体控件时遇到的问题及解决方法,包括改进的迭代方式和替代方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在百度知道看到这个一个问题:

【问题:】

点击button1之后只有两个按钮消失,再点击剩下两个才能消失。按我写的这个语句来说应该是一下子全部消失才对啊。求告诉哪出错了!十分只是初步悬赏,如果解决了了会有追加!!下面是button1点击事件的处理代码。。。
private void button1_Click(object sender, EventArgs e) { foreach (Control c in this.panel1.Controls)

这是click事件的处理办法
private void button1_Click(object sender, EventArgs e)
{
foreach (Control c in this.panel1.Controls)
{
c.Dispose();
}
}

 

【有网友有如下解答:】

我试了一下,是foreach遍历的问题
似乎Control在Dispose的时候会把自己从父控件的Controls集合中移出。那么,根据迭代器的设计规范,在迭代过程中集合不应该被改变,如果迭代器检查到集合被改变了应该抛出异常,但是这里没有抛出异常。【注1】
结果就是异常迭代——foreach没有遍历集合中所有内容。你在c.Dispose()前面或后面加个MessageBox就可以看出来了,foreach只执行了两次。
改成用for循环+索引方式访问元素就可以了:
for(int i=panel1.Controls.Count -1;i>=0;i--)
{
Control c=panel1.Controls[i];
c.Dispose();
}
或者直接清空Controls集合,等垃圾回收执行析构函数:
panel1.Controls.Clear();

【注1】
看了下ControlCollection的MoveNext源码,果然没有检查集合的改变:
public bool MoveNext()
{
if ((this.current < (this.controls.Count - 1)) && (this.current < (this.originalCount - 1)))
{
this.current++;
return true;
}
return false;
}
当你迭代完第二个元素后,this.controls.Count等于3-2=1this.current=1,迭代就停止了。实际上集合中还有两个元素。

 

【替代解决方案】

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}


Queue<Control> query = new Queue<Control>();//临时存储获取到的control控件
/// <summary>
/// 递归获取panel1上的所有控件,并临时存储到一个队列中
/// </summary>
/// <param name="item"></param>
void DS(Control item)
{
for (int i = 0; i < item.Controls.Count;i++ )
{
if (item.Controls[i].HasChildren)
{
DS(item.Controls[i]);
}
else
{
query.Enqueue(item.Controls[i]);
}

}


}
private void button1_Click(object sender, EventArgs e)
{
DS(panel1);
//删除遍历到的控件
while (query.Count != 0)
{
query.Dequeue().Dispose();
}
}
}
}

 

 

 

 

转载于:https://www.cnblogs.com/steed-zgf/archive/2012/04/03/2430819.html

### C# 遍历选中的控件 示例代码 在C#中,遍历选中的控件通常需要结合具体的容器(如 `Panel`、`GroupBox` 或 `TableLayoutPanel` 等)以及控件类型(如 `CheckBox`、`RadioButton` 等)。以下是一个通用的示例代码,用于遍历指定容器中的所有控件,并检查是否有被选中的项。 ```csharp public static List<Control> GetSelectedControls(Control.ControlCollection controls) { List<Control> selectedControls = new List<Control>(); foreach (Control control in controls) { // 检查是否为 CheckBox 并且已被选中 if (control is CheckBox checkBox && checkBox.Checked) { selectedControls.Add(checkBox); } // 检查是否为 RadioButton 并且已被选中 if (control is RadioButton radioButton && radioButton.Checked) { selectedControls.Add(radioButton); } // 如果控件控件,则递归遍历 if (control.HasChildren) { selectedControls.AddRange(GetSelectedControls(control.Controls)); } } return selectedControls; } ``` 此方法通过递归遍历控件集合,找到所有被选中的 `CheckBox` 和 `RadioButton` 控件,并将它们添加到一个列表中[^1]。用户可以通过调用该方法获取所有选中的控件。 #### 示例调用 假设有一个窗体,其中包含多个 `CheckBox` 和 `RadioButton`,可以使用以下代码调用上述方法: ```csharp private void btnCheckSelected_Click(object sender, EventArgs e) { List<Control> selectedControls = GetSelectedControls(this.Controls); foreach (Control control in selectedControls) { MessageBox.Show($"Selected Control: {control.Text}"); } } ``` 此代码会遍历当前窗体上的所有控件,并显示所有被选中的控件名称[^2]。 --- ### 说明 - **递归遍历**:如果某些控件(如 `Panel` 或 `GroupBox`)包含控件,则需要递归地调用 `GetSelectedControls` 方法以确保所有嵌套控件都被遍历到。 - **控件类型判断**:通过 `is` 关键字判断控件类型,并根据具体类型(如 `CheckBox` 或 `RadioButton`)进行操作。 - **灵活性**:此方法可以轻松扩展以支持其他类型的控件或条件。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值