2

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

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

我要么遗漏了一些小细节,要么有其他不正确的地方。有任何想法吗?

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

4

6 回答 6

3

这样做可能更简单:

foreach ( TextBox tb in this.Controls.OfType<TextBox>()) 
{
    if ((string)tb.Tag == "Filled")
    // .....
}
于 2013-05-03T14:04:49.553 回答
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();
于 2013-05-03T14:16:06.970 回答
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()方法是您的 Form 或从 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);
}

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

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()当然也需要该方法。

于 2013-05-03T14:24:55.677 回答
1

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

于 2013-05-03T14:04:12.757 回答
0

您是否从自己设置标签属性。这是一种string属性。所以你可以试试这个:

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

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

if (c.Text.Trim().Length == 0)
{
 Console.WriteLine(c.Name);
}
于 2013-05-03T14:12:36.953 回答
0

我建议使用以下语法:

foreach (Control c in Controls)
    if (c is TextBox)
于 2013-05-03T14:04:33.547 回答