0

I have some few cases in my WPF application that requires me to find a specific type of user control in a given user control. For example I'm having the following method that already works nicely:

    public static System.Windows.Controls.CheckBox FindChildCheckBox(DependencyObject d)
    {
        try
        {
            System.Windows.Controls.CheckBox chkBox = d as System.Windows.Controls.CheckBox;

            if (d != null && chkBox == null)
            {
                int count = System.Windows.Media.VisualTreeHelper.GetChildrenCount(d);
                for (int i = 0; i < count; i++)
                {
                    chkBox = FindChildCheckBox(System.Windows.Media.VisualTreeHelper.GetChild(d, i));
                    if (chkBox != null)
                        break;
                }
            }

            return chkBox;
        }
        catch
        {
            return null;
        }
    }

This method will help me to find a CheckBox in a given ListViewItem which allows me to check/uncheck the said CheckBox more conveniently.

However, I'd like to have this method more generic like for example:

public static T FindChildUserControl<T>(DependencyObject d)

Unfortunately I do not see how I can get this work. Can someone please help?

Ralf
  • 293
  • 5
  • 15

1 Answers1

2

You need to replace CheckBox with T and add a generic restraint (where) to the type argument.

For example I'm having the following method that already works nicely

Which is odd, as far as I can tell it would only work on nested CheckBoxes. This should on any combination of controls:

public static T FindChild<T>(DependencyObject d) where T : DependencyObject
{
    if (d is T)
        return (T)d;

    int count = System.Windows.Media.VisualTreeHelper.GetChildrenCount(d);
    for (int i = 0; i < count; i++)
    {
        DependencyObject child = FindChild<T>(System.Windows.Media.VisualTreeHelper.GetChild(d, i));
        if (child != null)
            return (T)child;
    }

    return null;
}

Usage:

CheckBox check = FindChild<CheckBox>(parent);

To get all children of a certain type, this should work nicely:

public static IEnumerable<T> FindChildren<T>(DependencyObject d) where T : DependencyObject
{
    if (d is T)
        yield return (T)d;

    int count = System.Windows.Media.VisualTreeHelper.GetChildrenCount(d);
    for (int i = 0; i < count; i++)
    {
        foreach (T child in FindChildren<T>(System.Windows.Media.VisualTreeHelper.GetChild(d, i)))
            yield return child;
    }
}

Usage:

foreach(CheckBox c in FindChildren<CheckBox>(parent))

This method will help me to find a CheckBox in a given ListViewItem which allows me to check/uncheck the said CheckBox more conveniently.

You should use MVVM instead. Walking down the VisualTree is a really hacky workaround.

Manfred Radlwimmer
  • 13,257
  • 13
  • 53
  • 62
  • This seems to work fine and I have to admit it look plain simple, however it was once again the details that I was struggeling with. As for your hint about 'walking down the VisualTree': I use this code to only fix a small problem in the view, the ViewModel will not be affected so I think I should be fine. – Ralf Feb 27 '18 at 10:16