How to get children of a WPF container by type?

This extension method will search recursively for child elements of the desired type:

public static T GetChildOfType<T>(this DependencyObject depObj) 
    where T : DependencyObject
{
    if (depObj == null) return null;

    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
    {
        var child = VisualTreeHelper.GetChild(depObj, i);

        var result = (child as T) ?? GetChildOfType<T>(child);
        if (result != null) return result;
    }
    return null;
}

So using that you can ask for MyContainer.GetChildOfType<ComboBox>().


All of these answers but one uses recursion which IMO is just lame :)

Get visual children:

public static IEnumerable<T> FindVisualChildren<T>([NotNull] this DependencyObject parent) where T : DependencyObject
{
    if (parent == null)
        throw new ArgumentNullException(nameof(parent));

    var queue = new Queue<DependencyObject>(new[] {parent});

    while (queue.Any())
    {
        var reference = queue.Dequeue();
        var count = VisualTreeHelper.GetChildrenCount(reference);

        for (var i = 0; i < count; i++)
        {
            var child = VisualTreeHelper.GetChild(reference, i);
            if (child is T children)
                yield return children;

            queue.Enqueue(child);
        }
    }
}

Get logical children:

public static IEnumerable<T> FindLogicalChildren<T>([NotNull] this DependencyObject parent) where T : DependencyObject
{
    if (parent == null)
        throw new ArgumentNullException(nameof(parent));

    var queue = new Queue<DependencyObject>(new[] {parent});

    while (queue.Any())
    {
        var reference = queue.Dequeue();
        var children = LogicalTreeHelper.GetChildren(reference);
        var objects = children.OfType<DependencyObject>();

        foreach (var o in objects)
        {
            if (o is T child)
                yield return child;

            queue.Enqueue(o);
        }
    }
}

Note that both deeply traverse trees, if you wish to stop at first encounter then change both codes to encompass the call to queue.Enqueue in an else block.


Children is a collection of UIElements. So you need to iterate over the items and determine for each item whether it is of the required type. Fortunately, there is already a Linq method for exactly this, namely Enumerable.OfType<T>, which you can conveniently call using Extension Method syntax:

var comboBoxes = this.MyContainer.Children.OfType<ComboBox>();

This method filters the collection based on their type and returns, in your case, only the elements of type ComboBox.

If you only want the first ComboBox (as your variable name might suggest), you can just append a call to FirstOrDefault() to the query:

var myComboBox = this.MyContainer.Children.OfType<ComboBox>().FirstOrDefault();