views:

283

answers:

4

I need to get all controls on a form that are of type x, I'm pretty sure I saw that code once in the past that used something like this:

dim ctrls() as Control
ctrls = Me.Controls(GetType(TextBox))

I know I can iterate over all controls getting children using a recursive function, but wondering if there is something more easier or straightforward, maybe:

Dim Ctrls = From ctrl In Me.Controls Where ctrl.GetType Is Textbox

Kind regards

+1  A: 

In C# (since you tagged it as such) you could use a LINQ expression like this:

List<Control> c = Controls.OfType<TextBox>().Cast<Control>().ToList();

Edit for recursion:

In this example, you first create the list of controls and then call a method to populate it. Since the method is recursive, it doesn't return the list, it just updates it.

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);
    }
}

It may be possible to do this in one LINQ statement using the Descendants function, though I am not as familiar with it. See this page for more information on that.

JYelton
Thanks, C# or VB is fine for me.But the problems is that Controls.OfType<TExtbox> only returns the childs of the current control(in my case the Form), and I want in a single call to get ALL controls in the Forma "recursively" (chiilds, sub-childs, sub-sub-childs,.....) in asingle collection.
Luis
I'll update the answer to be recursive.
JYelton
+1  A: 

You can use a LINQ query to do this. This will query everything on the form that is type TextBox

var c = from controls in this.Controls.OfType<TextBox>()
              select controls;
PsychoCoder
Thanks, but the same problema as the ther answer, it only returns the chidls but not the subchilds, etc, and I want all ensted controls.I'm pretty sure I saw that it is posible with a single method call that is new in .NET 3.5 or 4.0, remember I saw that in a demo somewehre
Luis
Ignoring the lack of recursion, wouldn't `var c = this.Controls.OfType<TextBox>()` give the same result?
Dennis Palmer
@Dennis: Yes it would, it's a matter of preference (usually). See http://stackoverflow.com/questions/214500/which-linq-syntax-do-you-prefer-fluent-or-query-expression for an interesting discussion on the matter.
JYelton
A: 

Maybe this one ?

Public Function getControls(Of T)() As List(Of T)
    Dim st As New Stack(Of Control)
    Dim ctl As Control
    Dim li As New List(Of T)

    st.Push(Me)

    While st.Count > 0
        ctl = st.Pop
        For Each c In ctl.Controls
            st.Push(CType(c, Control))
            If c.GetType Is GetType(T) Then
                li.Add(CType(c, T))
            End If
        Next
    End While

    Return li
End Function

I think the function to get all controls you are talking about is only available to WPF.

Cheers !

Alex Rouillard
A: 

Here's another option for you. I tested it by creating a sample application, I then put a GroupBox and a GroupBox inside the initial GroupBox. Inside the nested GroupBox I put 3 TextBox controls and a button. This is the code I used (even includes the recursion you were looking for)

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);
}

To test it in the form load event I wanted a count of all controls inside the initial GroupBox

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

And it returned the proper count each time, so I think this will work perfectly for what you're looking for :)

PsychoCoder