Andrew Whiddett on Visual Tree Helpers

Andrew Whiddett, from REZN8, who contributes useful snippets of code and learnings as he works with WPF, has offered up his own custom visual tree helper class, with explanation.  Thanks Andrew!

*******************************************************************

Some Visual Tree Helpers

Once you get up the curve (or cliff – I think cliff is more accurate :) ), one of the common things you want to do is find an existing element in the visual tree. There are a number of reasons you want to do this:

  • In a custom control you want to find a particular element type to interact with, such as the ScrollViewer or the ItemHost.
  • You want to give focus over to a particular element.
  • You want to find all of a particular type; for example to stop all video play back.
  • You want to interact with an element that may or not be somewhere in the visual tree: for example a pop up or something. We do that a lot in  our 3d space. i.e. Lose binding.

What happened for me is I hacked out the ‘find visual element’ from a sample and ended up creating about six or seven different variations of it. Not pretty at all. So. in my spare time I refactored the code so I could produce a simple to use common API to locate elements. But I needed to do something else clever: I wanted to be able to walk both down the visual tree (like in the existing routine) but I also wanted to be able to walk up the tree as well, so that I could make it as independent a helper class as possible. Well here it is. I am not going to do a walk through of the actual implementation of the code, after all it’s an API. Feel free to use it as you want, but I have included some usage documentation below.

First the structure:

There are two core static methods:

1. FindDownInTree(Visual root, IFinderMatchVisualHelper helper) – This locates matches (see below for more details on the matches interface) that exist in or below the ‘root’ visual element. Just to make things easier, there is a SingleFindDownInTree where you only want to find one element (most useful if you are looking for a named control, or something where there is only one of a type).
2. FindInTree(Visual root, IFinderMatchVisualHelper helper) – This attempts to locate matches that exist below the ‘root’ visual element, and then walks up the visual tree (i.e. to all the parents and children) of the whole visual tree from root. Again, there is a variation called SingleFindInTree.

The IFinderMatchVisualHelper interface defines two elements: DoesMatch and the StopAfterFirst property. This way we can extend the find routines to look for pretty well anything.. My implementation defines the following commonly used matching:

1. FinderMatchType – This looks for a particular Type.
2. FinderMatchName – This looks for a visual that has a given name.
3. FinderMatchFocused – This finds the visual that has the focus.
4. FinderMatchItemHost – This finds the item host – great for Item container methods.

Usage examples:

To find all the media elements in under a visual root and play any:

List<FrameworkElement> lst = BaseWPFHelpers.Helpers.FindDownInTree(parent, new FinderMatchType(typeof(MediaElement)));

foreach (FrameworkElement me in lst)
{
MediaElement meCast = me as MediaElement;

if (meCast != null)
{
try
{
meCast.Play();
}
catch (Exception e)
{
}
}
}

To find a named element called ‘foo’ anywhere in the visual tree:

FrameworkElement fe = BaseWPFHelpers.Helpers.SingleFindInTree(parent, new FinderMatchName(“foo”));
if(fe != null)
{
}

To find the Items host (for example in a method in a list box)…

FrameworkElement feHost = BaseWPFHelpers.Helpers.SingleFindDownInTree(this, new FinderMatchItemHost());

And just to hide the implementation more, I have also supplied the following static helpers, which cover the common usage patterns:

public static List<FrameworkElement> FindElementsOfType(Visual parent, Type ty)
public static FrameworkElement FindElementOfType(Visual parent, Type ty)
public static FrameworkElement FindFocusedElement(Visual parent)
public static FrameworkElement FindItemsHost(Visual parent)
public static FrameworkElement FindVisualElement(Visual parent, String ElementName)

Other stuff

There are also a couple of other helpers in this class:

• TurnOffMediaElements – Turns off all media elements under ‘root’. I use this when I bring something up modally.
• TurnOnMediaElements – Turns on all media elements under ‘root’.
• CreateImageBrushFromVisual – Helper to get a snapshot of an element – I use this for drag-n-drop, and when I am animating a move etc.

Have fun on the cliff face.

Andrew Whiddett

Download the code