This article discusses nuances of and differences between the visual tree and logical tree in WPF. It also presents a small application with which you can investigate this topic further. If you are completely unfamiliar with the concepts of the visual tree and/or logical tree, I suggest you read this page in the SDK documentation first.

Background

The existing documentation about the visual tree and logical tree in the Windows SDK leaves much to be desired. Ever since I started with WPF, I have felt unsure about what exactly differentiates the two. I knew that the logical tree and visual tree both only contain visual elements and controls, right? Wrong. I knew that a Window/Page/Control/etc. contains one and only one logical tree, right? Wrong. I knew what I was doing, right? Wrong.

It turns out that the element trees in WPF are rather complicated and require detailed knowledge of low-level WPF classes to work with them correctly. Walking an element tree in a generic fashion; where you assume no knowledge of its constituents; is not as simple as it might seem. Unfortunately WPF does not publicly expose a class which simplifies walking the element trees to the point where it is "really easy".

At this point you might be wondering what makes walking the element trees so complicated. Good question. The answer has several parts, which are discussed in the following sections.

The Visual Tree

The visual tree represents all of the elements in your UI which render to an output device (typically, the screen). The visual tree is used for many things like rendering, event routing, locating resources (if an element has no logical parent), and more. Walking up and down the visual tree can be a simple matter of just using VisualTreeHelper and some simple recursive methods.

However, there is one wrinkle which makes this a little more complicated. Anything which descends from ContentElement can appear in a user interface, but is not actually in the visual tree. WPF will "pretend" that those elements are in the visual tree, to facilitate consistent event routing, but it's just an illusion. VisualTreeHelper does not work with ContentElement objects because ContentElement does not derive from Visual or Visual3D. Here are all of the classes in the Framework which descend from ContentElement, as seen in Reflector: