Share via


VisualTreeHelper

A very useful class in Silverlight that is not as well known as it deserves to be is the VisualTreeHelper class. It contains four methods. One is FindElementsInHostCoordinates, which is used to programatically "hit test" the visual tree and determine what elements are under a given point in the plugin. This can be very useful at times (for example in drag-and-drop type scenarios).

The other three methods in the class, GetParent, GetChildrenCount and GetChild (all self explanatory) are used to navigate the visual tree. Silverlight (and also WPF) has two different concepts of the tree of UI elements; the "logical" tree and the "visual" tree. Roughly, the structure of the logical tree is what you see in XAML, whereas the visual tree also includes the expanded templates of any Controls/DataTemplates, etc. So for example if you have a Button containing an Image, then the Image is the logical child of the Button, but the visual children of the Button contains all of the chrome of the Button (the ControlTemplate as defined in generic.xaml), the ContentPresenter element which displays the Image and the Image element itself.

When it comes to manipulating the visual tree, I find that this is a useful extension method to have around:

public static IEnumerable<DependencyObject> GetVisuals(this DependencyObject root)

{

    int count = VisualTreeHelper.GetChildrenCount(root);

    for (int i = 0; i < count; i++)

    {

        var child = VisualTreeHelper.GetChild(root, i);

        yield return child;

        foreach (var descendants in child.GetVisuals())

        {

            yield return descendants;

        }

    }

}

(Note the use of the yield return syntax; another feature that is not as widely known about as it deserves.)

You can use this method to search through all of the children of a given element; much easier than trying to navigate through the tree using the element's object model (e.g. examining the "Children" property of Panels, the "Content" property of ContentControls, the "Child" property of Borders, etc.). Since it deals with IEnumerables, it also plays very nicely with LINQ expressions; consider this snippet of code to disable all the controls on a page:

 

foreach (var control in LayoutRoot.GetVisuals().OfType<Control>())

{

    control.IsEnabled = false;

}

 

VisualTreeHelper is a pretty simple class, but it can be extremely useful at times.