Accessing the Parent
       by kirupa  |  23 August 2009

In the previous page, you saw the code for the FindParentByType extension method and learned where to place it in your application. In this page, let's go ahead and wrap our general solution up and look at what makes Behaviors different.

Calling the Code (after the UserControl has Loaded)
The FindParentByType code works by traveling up each parent and checking if the parent you are looking for is here. In order for this to work, you need to ensure that your application has fully loaded to avoid any issues in Silverlight and WPF where you get errors because your visual tree has not fully been generated yet.

While this sounds scary, the solution is fairly simple. We need to make sure that our FindParentByType code does not get called until our user control has fully loaded. This requires hooking up the Loaded event and assigning an event handler. If you are not familiar with event handlers, learn more about them in my earlier Event Handlers in WPF tutorial. You can set up your event handler directly in XAML using Blend, or you can do it via code.

For the sake of simplicity, I am just going to do it via code. Go ahead and associate the Loaded event with an event handler inside the constructor for your user control, and place your event handler directly below your constructor.

Here is what my code looks like with the Loaded event and an event handler called ChildControl_Loaded:

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
InitializeComponent();
 
this.Loaded += new RoutedEventHandler(ChildControl_Loaded);
}
 
void ChildControl_Loaded(object sender, RoutedEventArgs e)
{
// What to run after you have loaded your application
}
}
 
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>();
}
}
}
}

The event handler that gets called, in my example, after everything loads is ChildControl_Loaded. Inside this method, you will make a call to the FindParentByType extension method. Because this is an extension method, you can just do something like this:

MainPage mainPage = this.FindParentByType<MainPage>();

Your full event handler code would look as follows:

void ChildControl_Loaded(object sender, RoutedEventArgs e)
{
MainPage mainPage = this.FindParentByType<MainPage>();
}

The FindParentByType extension method works like this. Let's say you have a parent/child structure as shown here:

In this example, the extension method lives in ChildControl (kind of like in all of my examples) and you wish to get a reference to its parent whose type is MyParentUserControl. Your call to FindParentByType would look as follows:

void ChildControl_Loaded(object sender, RoutedEventArgs e)
{
MyParentUserControl uc = this.FindParentByType<MyParentUserControl>();
}

Notice that FindParentByType does not take an argument in the traditional sense. Instead, it takes a type argument whose type matches the type of the parent you are looking for. If I wanted to go all the way to the top and access MainPage, I would simply do this:

void ChildControl_Loaded(object sender, RoutedEventArgs e)
{
MainPage uc = this.FindParentByType<MainPage>();
}

That is all there is to it. This general solution allows you to access both your immediate parent as well as any parent leading up to and including the root. Read that last line carefully. The key words to look for are "any parent".

Your parent does not have to be a UserControl or Window. For example, what is the parent of the UserControl that you see in the following example:

You may think that the UserControl at the top of the tree is the parent (especially given the themes of this particular article), but it actually is the Grid element called LayoutRoot. LayoutRoot's parent is Border, and only the Border has a parent whose type is UserControl.

The code for the general solution I have provided will find the first type of any parent it encounters - not just something that is a type belonging to UserControl. This means that you can use this solution to also find the Grid and Border parents from my example!

Behaviors and the Parent
I briefly mentioned behaviors on the first page of this tutorial, but I never mentioned them since then. The reason is, for the purposes of this tutorial, you can think of a behavior as a usercontrol that faces similar challenges when trying to access its parents and root element.

The only variation is that a Behavior (or Action) contains a mechanism for easily accessing its immediate parent - the object it is usually attached to. Behaviors and Actions have a property called AssociatedObject that returns the element they are nested under without any fuss:

this.AssociatedObject;

If your Behavior or Action is actually templated to only work on a particular type, the AssociatedObject property's type will be keyed to what the Behavior or Action is looking for without requiring any additional casting.

I mention that the AssociatedObject returns the immediate parent which is usually the same as the element your behavior or action is attached to. Because of retargeting, you cannot always assume that the parent of your behavior or action is actually the same as the AssociatedObject, so be aware of that.

Conclusion
Everything you do in Silverlight and WPF revolves around the concept of a tree containing parents and children. Visual and non-visual elements are nested under something and this relationship greatly impacts how your application looks as well as works.

Hopefully this tutorial helped you to figure out some ways of accessing the immediate parent or the root easily, for you will find yourself doing this often - especially if you design your application visually using Expression Blend where you do not have the ability to visually modify the constructor to take a reference to the parent element.

If you are interested in seeing an example of this working, download the source files for a sample Silverlight project where you have a deeply nested usercontrol calling the root using the FindParentByType:

Download Final Source Files

Just a final word before we wrap up. If you have a question and/or want to be part of a friendly, collaborative community of over 220k other developers like yourself, post on the forums for a quick response!

Kirupa's signature!

 

1 | 2 | 3




SUPPORTERS:

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