我需要获取表单上所有类型为X的控件。我很确定我在过去见过一次这样的代码:
dim ctrls() as Control
ctrls = Me.Controls(GetType(TextBox))
我知道我可以使用递归函数迭代所有控件获得子控件,但是有没有更简单或更直接的方法,可能像下面这样?
Dim Ctrls = From ctrl In Me.Controls Where ctrl.GetType Is Textbox
这是你的另一个选择。我通过创建一个示例应用程序来测试它,然后在初始GroupBox中放入一个GroupBox和一个GroupBox。在嵌套的GroupBox中,我放了3个TextBox控件和一个按钮。这是我使用的代码(甚至包括您正在寻找的递归)
public IEnumerable<Control> GetAll(Control control,Type type)
{
var controls = control.Controls.Cast<Control>();
return controls.SelectMany(ctrl => GetAll(ctrl,type))
.Concat(controls)
.Where(c => c.GetType() == type);
}
要在form load事件中测试它,我需要初始GroupBox内所有控件的计数
private void Form1_Load(object sender, EventArgs e)
{
var c = GetAll(this,typeof(TextBox));
MessageBox.Show("Total Controls: " + c.Count());
}
它每次都返回正确的计数,所以我认为这将完美地满足您的需求:)
在C#中(因为您将其标记为这样),您可以使用如下的LINQ表达式:
List<Control> c = Controls.OfType<TextBox>().Cast<Control>().ToList();
null
在本例中,您首先创建控件列表,然后调用一个方法来填充它。因为这个方法是递归的,所以它不返回列表,它只是更新列表。
List<Control> ControlList = new List<Control>();
private void GetAllControls(Control container)
{
foreach (Control c in container.Controls)
{
GetAllControls(c);
if (c is TextBox) ControlList.Add(c);
}
}
使用
编辑%2以返回集合:
正如@profk所建议的,简单地返回所需控件的方法可能是更好的实践。为了说明这一点,我对代码进行了如下修改:
private IEnumerable<Control> GetAllTextBoxControls(Control container)
{
List<Control> controlList = new List<Control>();
foreach (Control c in container.Controls)
{
controlList.AddRange(GetAllTextBoxControls(c));
if (c is TextBox)
controlList.Add(c);
}
return controlList;
}
这是递归GetAllControls()的改进版本,它实际上在私有变量上工作:
private void Test()
{
List<Control> allTextboxes = GetAllControls(this);
}
private List<Control> GetAllControls(Control container, List<Control> list)
{
foreach (Control c in container.Controls)
{
if (c is TextBox) list.Add(c);
if (c.Controls.Count > 0)
list = GetAllControls(c, list);
}
return list;
}
private List<Control> GetAllControls(Control container)
{
return GetAllControls(container, new List<Control>());
}