如何获取特定类型(按钮/文本框)的Windows窗体表单的所有子控件?

Lui*_*uis 113 .net c# vb.net controls winforms

我需要获取x类型的表单上的所有控件.我很确定我曾经使用过这样的代码:

dim ctrls() as Control
ctrls = Me.Controls(GetType(TextBox))
Run Code Online (Sandbox Code Playgroud)

我知道我可以迭代所有控件让孩子们使用递归函数,但是有更简单或更直接的东西,可能如下所示?

Dim Ctrls = From ctrl In Me.Controls Where ctrl.GetType Is Textbox
Run Code Online (Sandbox Code Playgroud)

Psy*_*der 216

这是你的另一个选择.我通过创建示例应用程序对其进行了测试,然后将GroupBox和GroupBox放在初始GroupBox中.在嵌套的GroupBox中,我放了3个TextBox控件和一个按钮.这是我使用的代码(甚至包括你正在寻找的递归)

public IEnumerable<Control> GetAll(Control control,Type type)
{
    var controls = control.Controls.Cast<Control>();

    return controls.SelectMany(ctrl => GetAll(ctrl,type))
                              .Concat(controls)
                              .Where(c => c.GetType() == type);
}
Run Code Online (Sandbox Code Playgroud)

要在表单加载事件中测试它,我想要计算初始GroupBox中的所有控件

private void Form1_Load(object sender, EventArgs e)
{
    var c = GetAll(this,typeof(TextBox));
    MessageBox.Show("Total Controls: " + c.Count());
}
Run Code Online (Sandbox Code Playgroud)

它每次返回正确的计数,所以我认为这将完美适合你正在寻找的:)

  • 这里定义的GetAll()是类Control的扩展方法的一个非常好的候选者 (20认同)
  • @soulblazer添加System.Linq命名空间. (2认同)

JYe*_*ton 31

在C#中(因为你标记了它)你可以使用这样的LINQ表达式:

List<Control> c = Controls.OfType<TextBox>().Cast<Control>().ToList();
Run Code Online (Sandbox Code Playgroud)

编辑递归:

在此示例中,首先创建控件列表,然后调用方法来填充它.由于该方法是递归的,因此它不会返回列表,只是更新它.

List<Control> ControlList = new List<Control>();
private void GetAllControls(Control container)
{
    foreach (Control c in container.Controls)
    {
        GetAllControls(c);
        if (c is TextBox) ControlList.Add(c);
    }
}
Run Code Online (Sandbox Code Playgroud)

使用该Descendants函数可以在一个LINQ语句中执行此操作,但我并不熟悉它.有关详细信息,请参阅此页面.

编辑2以返回集合:

正如@ProfK建议的那样,简单地返回所需控件的方法可能是更好的做法.为了说明这一点,我修改了代码如下:

private IEnumerable<Control> GetAllTextBoxControls(Control container)
{
    List<Control> controlList = new List<Control>();
    foreach (Control c in container.Controls)
    {
        controlList.AddRange(GetAllTextBoxControls(c));
        if (c is TextBox)
            controlList.Add(c);
    }
    return controlList;
}
Run Code Online (Sandbox Code Playgroud)


Vic*_*ina 13

这是递归GetAllControls()的改进版本,它实际上适用于私有变量:

    private void Test()
    {
         List<Control> allTextboxes = GetAllControls(this);
    }
    private List<Control> GetAllControls(Control container, List<Control> list)
    {
        foreach (Control c in container.Controls)
        {
            if (c is TextBox) list.Add(c);
            if (c.Controls.Count > 0)
                list = GetAllControls(c, list);
        }

        return list;
    }
    private List<Control> GetAllControls(Control container)
    {
        return GetAllControls(container, new List<Control>());
    }
Run Code Online (Sandbox Code Playgroud)


小智 8

我将一堆先前的想法合并到一个扩展方法中.这里的好处是你得到正确类型的可枚举,加上正确处理继承OfType().

public static IEnumerable<T> FindAllChildrenByType<T>(this Control control)
{
    IEnumerable<Control> controls = control.Controls.Cast<Control>();
    return controls
        .OfType<T>()
        .Concat<T>(controls.SelectMany<Control, T>(ctrl => FindAllChildrenByType<T>(ctrl)));
}
Run Code Online (Sandbox Code Playgroud)


Psy*_*der 7

您可以使用LINQ查询来执行此操作.这将查询表单TextBox上的所有内容

var c = from controls in this.Controls.OfType<TextBox>()
              select controls;
Run Code Online (Sandbox Code Playgroud)

  • @Dennis:是的,这是一个偏好(通常).有关此事的有趣讨论,请参见http://stackoverflow.com/questions/214500/which-linq-syntax-do-you-prefer-fluent-or-query-expression. (2认同)

Adi*_*ade 5

它可能是古老的技术,但它的魅力就像它一样.我使用递归来改变控件的所有标签的颜色.它很棒.

internal static void changeControlColour(Control f, Color color)
{
    foreach (Control c in f.Controls)
    {

        // MessageBox.Show(c.GetType().ToString());
        if (c.HasChildren)
        {
            changeControlColour(c, color);
        }
        else
            if (c is Label)
            {
                Label lll = (Label)c;
                lll.ForeColor = color;
            }
    }
}
Run Code Online (Sandbox Code Playgroud)


Oma*_*mar 5

一个干净简单的解决方案(C#):

static class Utilities {
    public static List<T> GetAllControls<T>(this Control container) where T : Control {
        List<T> controls = new List<T>();
        if (container.Controls.Count > 0) {
            controls.AddRange(container.Controls.OfType<T>());
            foreach (Control c in container.Controls) {
                controls.AddRange(c.GetAllControls<T>());
            }
        }

        return controls;
    }
}
Run Code Online (Sandbox Code Playgroud)

获取所有文本框:

List<TextBox> textboxes = myControl.GetAllControls<TextBox>();
Run Code Online (Sandbox Code Playgroud)