如何在Windows窗体中获取窗体的所有控件?

我有一个名为AForm

A包含许多不同的控件,包括主GroupBox 。 此GroupBox包含许多表和其他GroupBox 。 我想找到一个控件,其中包含例如表单A选项卡索引9,但我不知道哪个GroupBox包含此控件。

我怎样才能做到这一点?

随着递归……

 public static IEnumerable Descendants( this Control control ) where T : class { foreach (Control child in control.Controls) { T childOfT = child as T; if (childOfT != null) { yield return (T)childOfT; } if (child.HasChildren) { foreach (T descendant in Descendants(child)) { yield return descendant; } } } } 

你可以使用上面的function:

 var checkBox = (from c in myForm.Descendants() where c.TabIndex == 9 select c).FirstOrDefault(); 

这将获得TabIndex为9的表单中的第一个CheckBox。您显然可以使用您想要的任何条件。

如果您不是LINQ查询语法的粉丝,可以将上面的内容重写为:

 var checkBox = myForm.Descendants() .FirstOrDefault(x=>x.TabIndex==9); 

递归搜索表单的Controls集合。

 void FindAndSayHi(Control control) { foreach (Control c in control.Controls) { Find(c.Controls); if (c.TabIndex == 9) { MessageBox.Show("Hi"); } } } 

你可以制作这样的方法:

 public static Control GetControl(Control.ControlCollection controlCollection, Predicate match) { foreach (Control control in controlCollection) { if (match(control)) { return control; } if (control.Controls.Count > 0) { Control result = GetControl(control.Controls, match); if (result != null) { return result; } } } return null; } 

……就像这样使用:

 Control control = GetControl(this.Controls, ctl => ctl.TabIndex == 9); 

但请注意, TabIndex是一个棘手的情况,因为它在每个容器中从0开始,因此可能有多个控件在同一表单中具有相同的TabIndex值。

无论哪种方式,上面的方法可用于检查控件的几乎任何属性:

 Control control = GetControl(this.Controls, ctl => ctl.Text == "Some text"); 
 void iterateControls(Control ctrl) { foreach(Control c in ctrl.Controls) { iterateControls(c); } } 

我讨厌递归,所以我总是使用堆栈来做这种事情。 这为当前控件层次结构中的每个RadioButton控件的CheckedChanged事件分配了一个公共事件处理程序:

 Stack controlStack = new Stack(); foreach (Control c in this.Controls) { controlStack.Push(c); } Control ctl; while (controlStack.Count > 0 && (ctl = controlStack.Pop()) != null) { if (ctl is RadioButton) { (ctl as RadioButton).CheckedChanged += new EventHandler(rb_CheckedChanged); } foreach (Control child in ctl.Controls) { controlStack.Push(child); } } 

您可以轻松地改进Josh Einstein的扩展方法以这种方式工作。