Looping through child controls in WPF (C#)

Hey everyone,

As you all know, all I used to do was code all my stuff in Windows Forms. I’ve decided to switch over to WPF so I’m gently and at my own pace migrating from Windows Forms to WPF.
Everyone knows that when you migrate from one thing to another, you’ll always bump into the following problem:

“I was able to do this before, how am I supposed to do this now? ”

That has already happend a few times to me while working in WPF.

One of this issues I recently had, was that in Windows Forms it was easy to iterate over all the controls located within a form or container (GroupBox for example).
In WPF, it obviously didn’t work that way >.<

As an example, the following code in Windows Forms:

foreach(Control c in GroupBox1.Controls)
{
	if(c.GetType() == typeof(TextBox))
	{
		TextBox txt = (TextBox)c;
		txt.Clear();
	}
}

This would clear all textboxes located within GroupBox1.

Now, when you try to do that in WPF, you’ll notice that the GroupBox doesn’t have a Controls property.

So I had to put together a little helper that would get all the child controls for me and how deep they’d be nested:

class ChildControls
    {
        private List<object> lstChildren;

        public List<object> GetChildren(Visual p_vParent, int p_nLevel)
        {
            if (p_vParent == null)
            {
                throw new ArgumentNullException("Element {0} is null!", p_vParent.ToString());
            }

            this.lstChildren = new List<object>();

            this.GetChildControls(p_vParent, p_nLevel);

            return this.lstChildren;

        }

        private void GetChildControls(Visual p_vParent, int p_nLevel)
        {
            int nChildCount = VisualTreeHelper.GetChildrenCount(p_vParent);

            for (int i = 0; i <= nChildCount - 1; i++)
            {
                Visual v = (Visual)VisualTreeHelper.GetChild(p_vParent, i);
                
                lstChildren.Add((object)v);

                if (VisualTreeHelper.GetChildrenCount(v) > 0)
                {
                    GetChildControls(v, p_nLevel + 1);
                }
            }
        }
    }

Now with that class, I can simply do the following:

            ChildControls ccChildren = new ChildControls();

            foreach (object o in ccChildren.GetChildren(GroupBox1, 5))
            {
                if (o.GetType() == typeof(TextBox))
                {
                    TextBox txt = (TextBox)o;
                    txt.Text = "";
                }
            }

Note that the 5 in “.GetChildren(GroupBox1, 5)” indicates how many levels deep I’d like to check for controls.
When you have a layout that contains deeply nested XAML code, you can easily increase this number, especially when requesting child controls for top level elements

23 thoughts on “Looping through child controls in WPF (C#)”

    1. Duuurrrrrrrrrrr, I hate you 😛
      Go start your own blog instead of trolling mine! 😀

      I know there are probably easier ways or better ways then what I’ve just proposed. I just haven’t discovered it yet.

  1. You can also do this:

    foreach (var c in LogicalTreeHelper.GetChildren(GroupBox1)) {
    if (c is TextBox) {
    (c as TextBox).clear();
    }
    }

    1. Hey Nate,

      Won’t that snippet only loop over the children of the control and not the children of the children etc?

      As in:
      GroupBox1 –> GroupBox2 -> GroupBox3 –> TextBox2 won’t be found by that snippet?

      and only

      GroupBox1 –> TextBox1 will be found?

      Thanks for the comment btw, it’s always nice to know someone is reading ;P

      – Dirk

  2. Hi Dirk,

    After hours of trying to weed through the assistance that I found on the other blogs, I landed on your page. You’re a life saver…works great. This implementation is flexible enough to tool and retool for most anything a person wants to do with the controls on a form.

    Good job and thanks!

    I do have one question though. If I have several groupboxes on a form — what control do I replace the groupBox1 parameter with? The form name?

  3. U can add all controls in this and will work great, thxs

    ChildControls ccChildren = new ChildControls();

    foreach (object o in ccChildren.GetChildren(GroupBox1, 5))
    {
    if (o.GetType() == typeof(TextBox))
    {
    TextBox txt = (TextBox)o;
    txt.Text = “”;
    }
    if (o.GetType() == typeof(ComboBox))
    {
    ComboBox cm = (ComboBox)o;
    cm.SelectedIndex = -1;
    }

    if (o.GetType() == typeof(CheckBox))
    {
    CheckBox chk = (CheckBox)o;
    chk.IsChecked = false;
    }

    if (o.GetType() == typeof(RadioButton))
    {
    RadioButton chk = (RadioButton)o;
    chk.IsChecked = false;
    }

    if (o.GetType() == typeof(DatePicker))
    {
    DatePicker dtp = (DatePicker)o;
    dtp.SelectedDate = null;
    }
    }

    // Reset de Controles en WPF
    // WPF Reset Controls

  4. First off, thanks for the code! It worked for the most part in my case. My issue is the method is not clearing the controls for the remaining TabItems which are not selected. Other than that, it works great! Any suggestions on how to edit this so it’ll clear the rest of the controls in my TabItem’s Grid? Thanks!

  5. hello, I have a question: You have used the data type in your ChildControls class as Visual, while I am unable to use it in my code. I tried to look into it on the internet, but I found nothing. Can you please explain what the Visual data type is?

    1. Hello Meeha,

      When I wrote this article, I had just started to learn WPF (coming from a Winforms background).
      Several years later, I’ve had some WPF experiences and I can no longer recommend this approach.
      Pretty much anything can be done in WPF as long as you apply the MVVM pattern or use behaviors.

      That being said, the “Visual” class resides inside the “System.Windows.Media” namespace which is located in the “System.Windows” assembly.
      Add a reference to “System.Windows” in your project and you should have access to the “Visual” class.

      The class is abstract and inherits from DependencyObject.

  6. This is old and outdated, in addition, you have left us hanging with your last post on it. Please provide a way to return a list of all controls (recursively) on a WPF form (please assume the whole form not just a control 5 layers down). I would greatly appreciate it. Thank you in advance.

  7. Oh yeah and the old code did not specify any references or using statements, could you please include those?

    1. Hey LarryH,

      This is an old post indeed and I can no longer condone this kind of approach…
      I do no longer have the source code for this code snippet, although Visual Studio should be able to resolve the using statements that you need.

      As far as I can tell, the snippet keeps going down the visual tree until it no longer encounters any controls… It doesn’t do anything with the specified level :/

  8. Thanks Dirk,

    I’ve trying to figure this out for three days as I am new to programming.

    Although the solution came from Nate (Thanks Nate), I would never have found such a simple way to loop through the child controls.

    Thanks Again

  9. Dude,
    I know this is a 10+ year old post, but it delivers. Clear, concise, easy to use, no BS. Thanks a lot. I’d buy you a drink if I could 😉

Leave a Reply

Your email address will not be published.

 

This site uses Akismet to reduce spam. Learn how your comment data is processed.