Logical and Visual Trees

Summary

Windows Presentation Foundation (WPF) uses several tree structure
metaphors to define relationships between program elements. The primary tree
structure in WPF is the element tree. If you create an application
page in XAML, then the tree structure is created based on the nesting
relationships of the elements in the markup. understanding the concepts of how
the trees interact is a way to understand how property inheritance and event
routing work in WPF.

In WPF, you add content to elements using properties. For example,
you add items to a ListBox control using its
Items property. To add elements to a
DockPanel, you use its Children
property, and so on. In WPF, user interfaces are constructed from a tree of objects
known as a logical tree. A logical tree exists even for WPF user
interfaces that aren't created in XAML. The logical tree exists so that content
models can readily iterate over their possible child elements, and so that
content models can be extensible. Also, the logical tree provides a framework
for certain notifications, such as when all elements in the logical tree are
loaded. For example, for a ListBox with one
ListViewItem displaying a string,
the logical tree is this:

Why should you care about logical trees?
Because just about every aspect of WPF (properties, events, resources, and so
on) has behavior tied to the logical tree. For example, property values are
sometimes propagated down the logical tree to child elements automatically, and
raised events can travel up or down the tree. In addition, resource
references are resolved by looking upwards through the logical tree for
Resources collections on the initial requesting element and then parent elements.

A similar concept to the logical tree is the visual tree.
A visual tree is basically an expansion of a logical tree, in which
nodes are broken down into their core visual components. For example, if
a ListBox was an element in a logical tree, then the
visual tree will have all the core visual component making up the
ListBox such as the two scroll bars, borders, edit
areas, etc., then The visual tree describes the structure of
visuals represented by the Visual base class. When you write a template
for a control, you are defining or redefining the visual tree that applies for
that control. For example, for a ListBox with one
ListViewItem
displaying a string (logical tree shown above) the visual tree is this:

The following briefly describes some of the classes shown in the
visual tree:

ScrollViewer: Represents a
scrollable area that can contain other visible elements.

ScrollContentPresenter: Displays
the content of a ScrollViewer control.

ItemsPresenter: Used within the
template of an item control to specify the place in the controlís visual
tree where the ItemsPanel defined by the
ItemsControl is to be added.

VirtualizingStackPanel: Arranges
and virtualizes content on a single line that is oriented either
horizontally or vertically.

ContentPresenter: Displays the
content of a ContentControl.

You often don't need to worry about visual
trees unless you're doing low-level drawing. For example, although a
ListBox is logically a single control, its default
visual representation is composed of more primitive WPF elements: a
Border, two ScrollBars,
and many other visual elements. All controls that have a rendering behaviour
(those derive from System.Windows.Media.Visual or
System.Windows.Media.Visual3D) will appear in the
visual tree. However, unlike the visual tree, the logical tree can represent
nonvisual data objects, such as ListItem. One
exposure of the visual tree as part of conventional WPF application programming
is that event routes for a routed event mostly travel along the visual
tree, not the logical tree.

Content Elements are elements that inherit from
ContentElement class.
ContentElement class is a core-level base-class that defines common
content characteristics such as basic input from keyboard, mouse, drag-and-drop,
focus, and events. Content elements are not part of the visual tree; they do not
inherit from Visual and do not have a visual
representation. In order to appear in a UI at all, a
ContentElement must be hosted in a content host that is both a
Visual and a logical tree element, usually a
FrameworkElement.

Trees and Elements

When you instantiate a WPF class, several aspects of object
initialization are not part of class constructor code. Particularly for a
control class, most of the visual representation of that control is not
defined by the constructor. Instead, the visual representation is defined by the
control's template. The template potentially comes from a variety of
sources, but most often the template is obtained from theme styles.
Templates are effectively late-binding; the necessary template is not
attached to the control in question until the control is ready for layout. And
the control is not ready for layout until it is attached to a logical tree that
connects to a rendering surface at the root. It is that root-level element that
initiates the rendering of all of its child elements as defined in the logical
tree.

Tree Traversal

The LogicalTreeHelper class provides
the GetChildren, GetParent,
and FindLogicalNode methods for logical tree
traversal. In most cases, you should not have to traverse the logical tree of
existing controls, because these controls almost always expose their logical
child elements as a dedicated collection property that supports collection APIs
such as Add, an indexer, and so on. The visual tree
also supports a helper class for visual tree traversal,
VisualTreeHelper.

The figure below shows XamlPad rendering a simple XAML code. XamlPad contains a
button in its toolbar that reveals the visual tree (and property values) for any
XAML that it renders. It doesn't work when hosting a Window, but you can change
the Window element to a Page (and remove the SizeToContent property) to take
advantage of this functionality:

To programmatically traverse both the logical and visual trees, you
can use System.Windows.LogicalTreeHelper and
System.Windows.Media.VisualTreeHelper classes,
respectively.

The following code shows how to traverse both the visual tree and
the logical tree of the XAML given above. Note that whereas a logical tree is static without programmer
intervention (such as dynamically adding/removing elements), a visual tree can
change simply by a user switching to a different Windows theme. Therefore, avoid
writing code that depends on a specific visual tree. Also note that while the
logical tree can be traversed within a Window's
constructor, the visual tree is empty until the Window
undergoes layout at least once. That is why PrintVisualTree
must be called after content has been rendered (not before
OnContentRendered event was called):

Accessing Specific Visual Elements

The following example shows how VisualTreeHelper can be used to
access and change the background colour a ListBox
scrollbars:

// The input is assumed to
be a ListBox object.
public static void GetScrollBars(object obj)
{ // Get all children and examine if the
child is a ScrollBar
object obChild;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj as
DependencyObject); i++)
{
obChild =
VisualTreeHelper.GetChild(obj as DependencyObject, i);
if (obChild is ScrollBar)
{
// We found scroll bars. Change background color based on scroll bar orientation
if (((ScrollBar)obChild).Orientation
== System.Windows.Controls.Orientation.Horizontal)
((ScrollBar)obChild).Background = Brushes.Aquamarine;
else
((ScrollBar)obChild).Background = Brushes.Orange;
}
else
GetScrollBars(obChild);