Foreach循环通过文本框的控件不会返回

我之前在另一个程序中使用过此代码,但现在我无法理解为什么在第二行之后它不会运行代码。

foreach (Control c in Controls) if (c.GetType() == typeof(TextBox)) //doesn't run any further { if ((string)c.Tag == "Filled") { ... } ... } 

我要么错过了一些细微的细节,要么其他不正确的东西。 有任何想法吗?

编辑:我的文本框在面板内。

当您调用Control.Controls ,它只会返回最外层的控件。 它不会递归地下降到任何容纳其他控件的容器控件中。

如果您的控件位于另一个容器中,则需要使用该容器的.Controls属性。

或者你可以通过编写一个方法来概括它,以递归方式返回父项及其所有子项的所有控件,如下所示:

 public IEnumerable AllControls(Control container) { foreach (Control control in container.Controls) { yield return control; foreach (var innerControl in AllControls(control)) yield return innerControl; } } 

然后,您可以使用它而不是Control.Controls,如下所示:

 private void test() // Assuming this is a member of a Form other class derived from Control { var textboxesWithFilledTag = AllControls(this).OfType() .Where(tb => (string) tb.Tag == "Filled"); foreach (var textbox in textboxesWithFilledTag) Debug.WriteLine(textbox.Text); } 

正如评论所说,我假设test()方法是您的Form的成员或从Control派生的另一个类。 如果不是,则必须将父控件传递给它:

 private void test(Control container) { var textboxesWithFilledTag = AllControls(container).OfType() .Where(tb => (string) tb.Tag == "Filled"); foreach (var textbox in textboxesWithFilledTag) Debug.WriteLine(textbox.Text); } 

以下方法与上面的方法具有相同的结果,供参考(并且更具可读性恕我直言):

 private void test(Control container) { foreach (var textbox in AllControls(container).OfType()) if ((string)textbox.Tag == "Filled") Debug.WriteLine(textbox.Text); } 

对于您的代码,您的按钮单击处理程序可能如下所示:

 void button1_Click(object sender, EventArgs e) { foreach (var c in AllControls(this).OfType()) { if ((string) c.Tag == "Filled") { // Here is where you put your code to do something with Textbox 'c' } } } 

请注意,您当然还需要AllControls()方法。

这样做可能更简单:

 foreach ( TextBox tb in this.Controls.OfType()) { if ((string)tb.Tag == "Filled") // ..... } 

要获得所有控件(不仅是表单的直接子节点),您可以使用此递归Linq

 Func> allControls = null; allControls = c => new Control[] { c } .Concat(c.Controls.Cast() .SelectMany(x=>allControls(x))); 

现在您可以过滤TextBoxes

 var tbs = allControls(this).OfType() .Where(t=>(string)t.Tag=="Filled") .ToList(); 

if (c is TextBox)更好用。 此外,如果您想知道代码中断的原因,请使用try / catch

我建议使用以下语法:

 foreach (Control c in Controls) if (c is TextBox) 

你是自己设置标签属性吗? 这是一个string类型的属性。所以你可以试试这个:

 if (c.Tag == "Filled") { Console.WriteLine(c.Name); } 

如果你想检查文本框是否为空,那么你可以试试这个:

 if (c.Text.Trim().Length == 0) { Console.WriteLine(c.Name); }