通过文本框中的控件的Foreach循环不返回
本文关键字:Foreach 循环 返回 控件 文本 | 更新日期: 2023-09-27 18:11:55
我以前在另一个程序中使用过这段代码,但是现在我很难理解为什么它不会在第二行之后运行代码。
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<Control> AllControls(Control container)
{
foreach (Control control in container.Controls)
{
yield return control;
foreach (var innerControl in AllControls(control))
yield return innerControl;
}
}
你可以用它来代替Control。控件如下:
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()
方法。
这样做可能更简单:
foreach ( TextBox tb in this.Controls.OfType<TextBox>())
{
if ((string)tb.Tag == "Filled")
// .....
}
要获取所有控件(不仅仅是表单的直接子控件),您可以使用这个递归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();
最好使用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);
}