Introduction
I had recently come across a scenario where I wanted to locate a child control inside another control. After some digging around, I was able to find a method that locates an ancestor, but was not able to find anything to locate a child.
So I decided to write some stuff of my own (based on the Find Ancestor code).
The Code
The problem with locating a child instance, knowing the type, is that we need to look through multiple children to find that type. Remember, any child can have more children and so on and so forth. So, obviously, recursion comes into the picture.
Again, another issue is, a set of children can contain multiple instances of the type we are looking for.
E.g. I am looking for a text block inside my grid below. Now which one would I return?
<Grid>
<TextBlock x:Name=”1”/>
<TextBlock x:Name=”2”/>
</Grid>
Luckily, my scenario did not have such multiple instances. SO this is what I ran to find my child type.
public static DependencyObject FindChild
(DependencyObject dependencyObject, Func<DependencyObject, bool> predicate)
{
if (searched != null) return searched;
DependencyObject child = null;
FrameworkElement frameworkElement = dependencyObject as FrameworkElement;
if (frameworkElement != null)
{
int intCount =
System.Windows.Media.VisualTreeHelper.GetChildrenCount(frameworkElement);
for (int i = 0; i < intCount; i++)
{
child = System.Windows.Media.VisualTreeHelper.GetChildrenCount
(frameworkElement) == 0 ? null :
System.Windows.Media.VisualTreeHelper.GetChild(frameworkElement, i);
if (predicate(child))
{
searched = child; break;
}
FindChild(child, predicate);
}
}
return searched;
}
This probably is resource intensive, as we are going to recursively look for a control instance among many children who could have many children and so on. But it worked for me!
You can download the source code for my sample. It's not the fanciest in the world, but it gives a fair idea of what I was trying to achieve.
One thing that we could do to get a specific instance of a control would be to use a FrameworkElement
object's FindName
method, but that would mean knowing the name of your control (from the XAML). This may not be possible at all times.
History
- 20th May 2009: Article uploaded