Walking the WPF Control Hierarchy

I just finished teaching a Silverlight/WPF course last week. As is true in almost every course I teach, there were questions from people who are trying to use the technology in the real world. It's what I love about teaching...that I always learn something about how people use the tools they have been given.

In this particular case, the problem was relating to walking the control hierarchy in a user control. The user control contained a DataGrid and the goal was to get from a particular cell within the DataGrid back to the user control itself. The code that was written to do so looks approximately like the following.

public UserControl GetContainingUserControl(FrameworkElement element)

{

   if (element is UserControl)

      return element;

   else

      return GetContainingUserControl(element.Parent);

}

The problem with the code is that, in the case specified, the Parent becomes null before the UserControl is found. For most developers, this is a strange and unexpected turn of affairs. For most hierarchies, it seems completely reasonable to presume that every element in a hierarchy will have a non-null parent except the root of the tree. But if you read over the description of the Parent property closely, you will see that it could be null. From MSDN,

Parent may be a null reference (Nothing in Visual Basic) in cases where an object was instantiated, but is not attached to an object that eventually connects to the Silverlight RootVisual, or the application object.

Ouch. Sure it's documented, but still. Ouch.

Fortunately, there is a solution, found in an incredibly useful class named VisualTreeHelper. This class exposes a number of methods that can be used to navigate up and down the visual hierarchy in a WPF interface component. There is, for example, a GetChild method that retrieves a particular child element. As well, of particular interest for this example, there is a GetParent method that retrieves the parent of a given element. This method will not return a null parent until the top of the visual hierarchy is reached.

In other words,VisualTreeHelper.GetParent(element) can be used in place of element.Parent in the above method with the result being more in line with expectations.

Whew.