2013-05-03 52 views
1

我已经在另一个程序中使用过此代码,但现在我无法理解为什么它不会在我的第二行之后运行代码。通过文本框控件的foreach循环不返回

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

我要么丢失一些小的细节,要么其他东西不正确。有任何想法吗?

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

+0

也许你没有在控件中的文本框? – dasblinkenlight 2013-05-03 14:02:38

+0

你得到了什么错误? – 2013-05-03 14:03:59

+1

您是否使用调试器来遍历代码?您可以检查变量的值。 – Dirk 2013-05-03 14:04:01

回答

2

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

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

或者,你可以写一个方法来递归返回所有从父控件和它所有的孩子,像这样概括它:

public IEnumerable<Control> 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<TextBox>() 
     .Where(tb => (string) tb.Tag == "Filled"); 

    foreach (var textbox in textboxesWithFilledTag) 
     Debug.WriteLine(textbox.Text); 
} 

正如评论说,我假定test()方法是你的表格的成员或者从Control派生的类。如果不是,则必须给父控制传递给它:

private void test(Control container) 
{ 
    var textboxesWithFilledTag = 
     AllControls(container).OfType<TextBox>() 
     .Where(tb => (string) tb.Tag == "Filled"); 

    foreach (var textbox in textboxesWithFilledTag) 
     Debug.WriteLine(textbox.Text); 
} 

以下的方法具有相同的结果向所述一个以上,以供参考(和更具有可读性IMHO):

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

为您的代码,你按一下按钮处理程序可能是这个样子:

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

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

+0

我了解您对发布的第一部分代码所说的话。所以在我使用这段代码之后,我没有按照我在按钮单击事件中所做的操作。 – KFP 2013-05-03 14:43:34

+0

@KFP我已经添加了我认为您的按钮点击处理程序将看起来像我的答案结束。 – 2013-05-03 15:03:31

1

更好地使用if (c is TextBox)。 此外,如果你想知道为什么你的代码休息,使用try/catch语句

0

我建议使用下面的语法:

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

这可能是这样更简单:

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

标记不是一个字符串,所以我相信你需要添加'.ToString()',我不能验证这个.. – Sayse 2013-05-03 14:11:03

+0

好点 - 但我认为现在有很多OP的选项:-) – 2013-05-03 14:16:27

0

您是否正在设置tag属性。这是一个string型property.so你可以试试这个:

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

如果要检查文本框是不是空的,那么你可以简单地尝试这个办法:

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

要获得所有控制(不仅是形式的直接孩子),你可以使用这个递归的LINQ

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

现在,您可以过滤文本框

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