WPF Visual and Logical Trees

WPF’s hierarchical structure requires a new conceptual model of application structure, which takes the form of an element tree. Two types of element trees are required to adequately represent an element structure: a Logical Tree and a Visual Tree.

Logical trees are fairly simple to see in your code if you know where to look. The easiest way to understand a logical tree is to just look at the XAML definition of an element. The logical tree is the same as the XAML hierarchy down to Content child elements like Strings. The Logical Tree is basically the set of programmable elements available outside of the XAML declaration. If you’re not working with XAML (changing templates, styles etc.) or working on custom controls at a low level the Logical Tree is probably the one you should be thinking about. Except for some very rare cases an element’s Logical Tree is also smaller and simpler than its Visual Tree.

Visual trees are harder to visualize by just looking at code because they include every contained object that derives from either Visual or Visual3D, including those contained inside other sub-elements (XamlPad, included with the Vista SDK, includes a Visual Tree Explorer that shows a tree view of the complete visual tree of the current content.). Even something as simple as a Label has 3 more elements below it in its Visual Tree. Further complicating the task of mentally parsing a Visual Tree by reading the XAML is the fact that Visual Trees aren’t fixed for any control but can be completely changed by applying a new template!

The ramifications of this, when combined with the desired separation of XAML (to a designer) and code-behind (to a developer), include the ability of a developer to interact in code with Visual Tree elements that a designer has removed or replaced with something else in a new template in XAML! In this case the developer has violated the sacred separation of design and logic, but if they are not aware of the Visual Tree concept it may seem perfectly logical to assume that the Border of a TextBox, for instance, can be directly manipulated without consequence.

Another place where Visual Trees show up is in the reuse of visual elements as Resources. At first glance it seems like loading a jpg into an Image element as a resource would allow you to use that image resource many times while only incurring the loading of the image once. This would be in line with the traditional concept of a resource (WPF does also have traditional embedded resources that are different than these XAML resources). In WPF however, the Image element that is created is not a jpg resource, but an instance of the Image class, which is derived from Visual. This means that when this resource is used it is incorporated into the Visual Tree of its parent. Since element instances can only live in a single Visual Tree (possible consequences if that weren’t true = whole other rabbit hole), any attempt to reuse the Image resource results in an exception. The workaround for this is to include a Shared=”false” attribute in the Image declaration, which then causes a new instance to be created for each usage of the resource. This may seem like a waste of the resource concept, but keep in mind that that Image resource declared in XAML is not just the jpg itself, but an instance of the Image class, including, for example, all of its Dependency Properties which can be set based on its individual parent’s DependencyProperty settings.

The LogicalTreeHelper and VisualTreeHelper classes allow you to traverse these element trees in code at runtime. This can allow you to safely manipulate objects in the Visual Tree that may or may not exist at any given time depending on current control templates. You should probably avoid direct manipulation of the Visual Tree anyway, but if you do run into a situation where you need to, the VisualTreeHelper is the way.

Leave a Reply

Your email address will not be published. Required fields are marked *