In this page: Understanding the Visual Tree and Logical Tree in WPF , the difference between the Visual Tree and Logical Tree is discussed.
Visual Tree and Logical Tree
In summary.
Visual Tree
- represents all of the elements in your UI which render to an output device (typically, the screen)
- Used for rendering, event routing, and locating resource (if an element has no logical parent)
Logical Tree
- Represents the essential structure of your UI. It closely matches the elemtns you declared in XAML, and excludes most visual elements create internally to help render the elements you declared.
- WPF use logical tree to determine several things including dependency proeprty value inheritence, resource resolution and more.
How to walk down/up the VisualTree and the Logical Tree
with the Help of VisualTreeHelper, you can do
- VisualTreeHelper.GetParent(depObj)
- VisualTreeHelper.GetChildren(depObj)
and with the help of LogicalTreeHelper, you can do
- LogicalTreeHelper.GetParent(depObj);
- LogicalTreeHelper.GetChildren(depObj);
Below shows some helper function to help you find a parent of a specific type
DependencyObject parent = ExVisualTreeHelper.FindVisualParent<UserControl>(this); public static class ExVisualTreeHelper { /// <summary> /// Finds the visual parent. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="sender">The sender.</param> /// <returns></returns> public static T FindVisualParent<T>(DependencyObject sender) where T : DependencyObject { if (sender == null) { return (null); } else if (VisualTreeHelper.GetParent(sender) is T) { return (VisualTreeHelper.GetParent(sender) as T); } else { DependencyObject parent = VisualTreeHelper.GetParent(sender); return (FindVisualParent<T>(parent)); } }
You can do the same for LogicalTree.
Remove Visual/Logical Child
You may sometimes require to remove a child from a visual tree or logical tree (actually still investigating when this is justified).
There are two method for the class FrameworkElement.
FrameworkElement.RemoveLogicalChild
FrameworkElement.RemoveVisualChild
But they are protected internal method. Generally there are two ways to get around this.
- inherit and override
- reflection call.
Below show the code to do the reflection call.
private System.Reflection.MethodInfo GetMethodInfo(string name) { if (string.IsNullOrEmpty(name)) throw new ArgumentNullException("name"); var windowType = typeof(FrameworkElement); var methodinfo = windowType.GetMethod(name, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.InvokeMethod); if (methodinfo != null) return methodinfo; return null; } private void CallRemoveLogicalChild(FrameworkElement window, object child) { if (window == null) throw new ArgumentNullException("window"); if (child == null) throw new ArgumentNullException("child"); var method = GetMethodInfo("RemoveLogicalChild"); if (method != null) { method.Invoke(window, new[] { child }); } } private void CallRemoveVisualChild(FrameworkElement window, object child) { if (window == null) throw new ArgumentNullException("window"); if (child == null) throw new ArgumentNullException("child"); var method = GetMethodInfo("RemoveVisualChild"); if (method != null) { method.Invoke(window, new[] { child }); } }