Accessing the Parent
       by kirupa  |  23 August 2009

In the previous page, I explained how to directly access the root element. There is more to calling parents than just going directly to the root, so let's look at a more general solution that allows you to access all kinds of parents!

A General Solution
The above example is specific only to accessing the root of your application. You may find yourself in cases where you are in a deeply nested usercontrol and you need to access a parent that is somewhere below your root.

In my diagram, this is the example of the Yellow UserControl trying to call something on the Blue UserControl:

 

To handle situations like this, we need a more generalized solution. We need a solution that not only allows you to access the root parent, but it also needs to be something that we can use to access any intermediate parents as well.

Fortunately, that is doable, but it does require some additional work. First, the code for our generalized solution (aptly placed in a class called FindParentByType) is as follows:

public static class TreeHelper
{
public static T FindParentByType<T>(this DependencyObject child) where T : DependencyObject
{
Type type = typeof(T);
DependencyObject parent = VisualTreeHelper.GetParent(child);
 
if (parent == null)
{
return null;
}
else if (parent.GetType() == type)
{
return parent as T;
}
else
{
return parent.FindParentByType<T>();
}
}
}

Using the above code is not as straightforward as the one line you had for accessing the root element I showed you earlier. There are two things you need to do:

  1. This code creates is an extension method, so you need to place this file in a separate class.
  2. Before calling this code, you need to ensure that the usercontrol you are currently in has been fully loaded.

Don't worry, I'll explain how to do both of those things, so let's start with where to place an extension method.

Where to Paste the Code
When you look at your code behind file in a user control, you probably see something that looks like this:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
 
namespace ParentRootInteraction
{
public partial class ChildControl : UserControl
{
public ChildControl()
{
// Required to initialize variables
}
}
}

There will be a billion using statements, your namespace declaration, your usercontrol's class declaration, and finally the constructor for your class.

Because what you are creating is an extension method, it needs to live in its own class and not, as is the case with my example, ChildControl. So paste the FindParentByType extension method at the end of the last bracket that represents your class:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
 
namespace ParentRootInteraction
{
public partial class ChildControl : UserControl
{
public ChildControl()
{
// Required to initialize variables
}
}
 
public static class TreeHelper
{
public static T FindParentByType<T>(this DependencyObject child) where T : DependencyObject
{
Type type = typeof(T);
DependencyObject parent = VisualTreeHelper.GetParent(child);
 
if (parent == null)
{
return null;
}
else if (parent.GetType() == type)
{
return parent as T;
}
else
{
return parent.FindParentByType<T>();
}
}
}
}

Notice that I copied all of the code from the TreeHelper class (where FindParentByType lives) and placed it directly after where my ChildControl class ends.

Great! We just finished the first part where you placed the code in the appropriate location. The next part is to actually call the FindParentByType code to help us out, so let's do that on the next page.

Onwards to the next page!

1 | 2 | 3




SUPPORTERS:

kirupa.com's fast and reliable hosting provided by Media Temple.