This blog post demonstrates a Linq API which can be used to query the WPF / Silverlight Visual Tree. You can find a few other Linq to Visual Tree techniques on other blogs, but what makes this one unique is that it retains, and allows queries that make use of the tree like structure rather than simply flattening it.

I have recently published an article on codeproject which describes a technique for generating Linq API for querying tree-like structures. This blog post makes use of a generated API for WPF / Silverlight. If you are interested in the more generic approach, and how this API was constructed, (and how it is influenced by XPath) head on over to codeproject …
What I will provide here is a brief overview of the Linq to Visual Tree API. The full sourcecode for this API is at the end of this article.
The Linq to Visual Tree API defines a number of extension methods on DependencyObject that provide mechanisms for navigating to other DependencyObject instances. I will provide a few examples that query the following simple markup:
<Grid x:Name="GridOne" Background="White"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <TextBox x:Name="TextBoxOne" Text="One" Grid.Row="0" /> <StackPanel x:Name="StackPanelOne" Grid.Row="1"> <TextBox x:Name="TextBoxTwo" Text="Two" /> <Grid x:Name="GridTwo"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <TextBox x:Name="TextBoxThree" Text="Three" Grid.Row="0" /> <StackPanel x:Name="StackPanelTwo" Grid.Row="1"> <TextBox x:Name="TextBoxFour" Text="Four"/> </StackPanel> </Grid> </StackPanel> </Grid> |
We’ll start with a simple example. Include the Linq to Visual Tree namespace, then use the Descendants method to obtain all the descendants (i.e. children and children’s children, etc …) of an object within the
visual tree.
Descendants

using LinqToVisualTree; // all items within the visual tree IEnumerable<DependencyObject> allDescendants = this.Descendants(); /* gives ... 0 {Grid} [GridOne] 1 {TextBox} [TextBoxOne] 2 {StackPanel} [StackPanelOne] 3 {TextBox} [TextBoxTwo] 4 {Grid} [GridTwo] 5 {TextBox} [TextBoxThree] 6 {StackPanel} [StackPanelTwo] 7 {TextBox} [TextBoxFour] */ // all items within the visual tree of 'GridTwo' var descendantsOfGridTwo = GridTwo.Descendants(); /* gives ... 0 {TextBox} [TextBoxThree] 1 {StackPanel} [StackPanelTwo] 2 {TextBox} [TextBoxFour] */ |
Each of the extension methods also has a corresponding method with a generic type parameter that filters the collection to find elements of a specific type:
// all items within the visual tree of 'GridTwo' that are textboxes var textBoxDescendantsOfGridTwo = GridTwo.Descendants() .Where(i => i is TextBox); /* 0 {TextBox} [TextBoxThree] 1 {TextBox} [TextBoxFour] */ // a shorthand using the generic version of Descendants var textBoxDescendantsOfGridTwo2 = GridTwo.Descendants<TextBox>(); /* 0 {TextBox} [TextBoxThree] 1 {TextBox} [TextBoxFour] */ |
Elements
The elements extension method obtains all the direct children of an item in the visual tree:
// find all direct children of this user control var userControlChildren = this.Elements(); /* 0 {Grid} [GridOne] */ // find all direct children of the grid 'GridTwo' var gridChildren = GridTwo.Elements(); /* 0 {TextBox} [TextBoxThree] 1 {StackPanel} [StackPanelTwo] */ // find all direct children of the grid 'GridTwo' that are StackPanels var gridChildren2 = GridTwo.Elements<StackPanel>(); /* 0 {StackPanel} [StackPanelTwo] */ |
There are also, ElementsBeforeSelf and ElementsAfterSelf methods that return the elements before and after the item which the method is being invoked upon.
Ancestors
The ancestors methods traverse the tree towards the root, finding all the ancestors:
// the ancestors for 'TextBoxFour' var ancestors = TextBoxFour.Ancestors(); /* 0 {StackPanel} [StackPanelTwo] 1 {Grid} [GridTwo] 2 {StackPanel} [StackPanelOne] 3 {Grid} [GridOne] 4 {MainPage} [] */ // the ancestors for 'TextBoxFour' that are StackPanels var stackPanelAncestors = TextBoxFour.Ancestors<StackPanel>(); /* 0 {StackPanel} [StackPanelTwo] 1 {StackPanel} [StackPanelOne] */ |
Putting it all together
The Linq to Tree API not only defines extension methods on DependencyObject, but also the same extension methods on IEnumerable<DependencyObject>. Unless you have previous experience of Linq to XML, I would strongly suggest reading my codeproject article to understand how this works!
This allows you to form much more complex queries. For example, you can find all TextBoxs that have a Grid as a direct parent:
var itemsFluent = this.Descendants<TextBox>() .Where(i => i.Ancestors().FirstOrDefault() is Grid); var itemsQuery = from v in this.Descendants<TextBox>() where v.Ancestors().FirstOrDefault() is Grid select v; /* 0 {TextBox} [TextBoxOne] 1 {TextBox} [TextBoxThree] */ |
Here, you can also see we are mixing the fluent and query syntax for Linq. Both give the same result.
The next example finds all StackPanels that are within another StackPanels visual tree:
var items2Fluent = this.Descendants<StackPanel>() .Descendants<StackPanel>(); var items2Query = from i in (from v in this.Descendants<StackPanel>() select v).Descendants<StackPanel>() select i; /* 0 {StackPanel} [StackPanelTwo] */ |
Finally, this one-liner, outputs the entire visual tree in ASCII! It makes use of the DescendantsAndSelf, Ancestors and ElementsBeforeSelf methods, plus the funky Linq Aggregate method.
string tree = this.DescendantsAndSelf().Aggregate("", (bc, n) => bc + n.Ancestors().Aggregate("", (ac, m) => (m.ElementsAfterSelf().Any() ? "| " : " ") + ac, ac => ac + (n.ElementsAfterSelf().Any() ? "+-" : "\\-")) + n.GetType().Name + "\n"); |
\-MainPage
\-Grid
+-TextBox
| \-Grid
| +-Border
| | \-Grid
| | +-Border
| | \-Border
| | \-ScrollViewer
| | \-Border
| | \-Grid
| | +-ScrollContentPresenter
| | | \-TextBoxView
| | +-Rectangle
| | +-ScrollBar
| | \-ScrollBar
| +-Border
| +-Border
| \-Border
| \-Grid
| +-Path
| \-Path
\-StackPanel
+-TextBox
| \-Grid
| +-Border
| | \-Grid
| | +-Border
| | \-Border
| | \-ScrollViewer
| | \-Border
| | \-Grid
| | +-ScrollContentPresenter
| | | \-TextBoxView
| | +-Rectangle
| | +-ScrollBar
| | \-ScrollBar
| +-Border
| +-Border
| \-Border
| \-Grid
| +-Path
| \-Path
\-Grid
+-TextBox
| \-Grid
| +-Border
| | \-Grid
| | +-Border
| | \-Border
| | \-ScrollViewer
| | \-Border
| | \-Grid
| | +-ScrollContentPresenter
| | | \-TextBoxView
| | +-Rectangle
| | +-ScrollBar
| | \-ScrollBar
| +-Border
| +-Border
| \-Border
| \-Grid
| +-Path
| \-Path
\-StackPanel
\-TextBox
\-Grid
+-Border
| \-Grid
| +-Border
| \-Border
| \-ScrollViewer
| \-Border
| \-Grid
| +-ScrollContentPresenter
| | \-TextBoxView
| +-Rectangle
| +-ScrollBar
| \-ScrollBar
+-Border
+-Border
\-Border
\-Grid
+-Path
\-Path
Note: this was invoked after the LayoutUpdated event so that we not only see the elements from our XAML, but also the elements created from their templates, giving us our full run-time visual tree.
You can download a simple Silverlight application that demonstrated all the examples given above:
LinqToTree.zip.
Or, if you just want the Linq to VisualTree code, you can copy-n-paste from the windows below which has the entire API, which includes the methods illustrated above, plus their IEnumerable equivalents, and a few others I have not illustrated.
using System;
using System.Linq;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
namespace LinqToVisualTree
{
/// <summary>
/// Adapts a DependencyObject to provide methods required for generate
/// a Linq To Tree API
/// </summary>
public class VisualTreeAdapter : ILinqTree<DependencyObject>
{
private DependencyObject _item;
public VisualTreeAdapter(DependencyObject item)
{
_item = item;
}
public IEnumerable<DependencyObject> Children()
{
int childrenCount = VisualTreeHelper.GetChildrenCount(_item);
for (int i = 0; i < childrenCount; i++)
{
yield return VisualTreeHelper.GetChild(_item, i);
}
}
public DependencyObject Parent
{
get
{
return VisualTreeHelper.GetParent(_item);
}
}
}
}
namespace LinqToVisualTree
{
/// <summary>
/// Defines an interface that must be implemented to generate the LinqToTree methods
/// </summary>
/// <typeparam name="T"></typeparam>
public interface ILinqTree<T>
{
IEnumerable<T> Children();
T Parent { get; }
}
public static class TreeExtensions
{
/// <summary>
/// Returns a collection of descendant elements.
/// </summary>
public static IEnumerable<DependencyObject> Descendants(this DependencyObject item)
{
ILinqTree<DependencyObject> adapter = new VisualTreeAdapter(item);
foreach (var child in adapter.Children())
{
yield return child;
foreach (var grandChild in child.Descendants())
{
yield return grandChild;
}
}
}
/// <summary>
/// Returns a collection containing this element and all descendant elements.
/// </summary>
public static IEnumerable<DependencyObject> DescendantsAndSelf(this DependencyObject item)
{
yield return item;
foreach (var child in item.Descendants())
{
yield return child;
}
}
/// <summary>
/// Returns a collection of ancestor elements.
/// </summary>
public static IEnumerable<DependencyObject> Ancestors(this DependencyObject item)
{
ILinqTree<DependencyObject> adapter = new VisualTreeAdapter(item);
var parent = adapter.Parent;
while (parent != null)
{
yield return parent;
adapter = new VisualTreeAdapter(parent);
parent = adapter.Parent;
}
}
/// <summary>
/// Returns a collection containing this element and all ancestor elements.
/// </summary>
public static IEnumerable<DependencyObject> AncestorsAndSelf(this DependencyObject item)
{
yield return item;
foreach (var ancestor in item.Ancestors())
{
yield return ancestor;
}
}
/// <summary>
/// Returns a collection of child elements.
/// </summary>
public static IEnumerable<DependencyObject> Elements(this DependencyObject item)
{
ILinqTree<DependencyObject> adapter = new VisualTreeAdapter(item);
foreach (var child in adapter.Children())
{
yield return child;
}
}
/// <summary>
/// Returns a collection of the sibling elements before this node, in document order.
/// </summary>
public static IEnumerable<DependencyObject> ElementsBeforeSelf(this DependencyObject item)
{
if (item.Ancestors().FirstOrDefault() == null)
yield break;
foreach (var child in item.Ancestors().First().Elements())
{
if (child.Equals(item))
break;
yield return child;
}
}
/// <summary>
/// Returns a collection of the after elements after this node, in document order.
/// </summary>
public static IEnumerable<DependencyObject> ElementsAfterSelf(this DependencyObject item)
{
if (item.Ancestors().FirstOrDefault() == null)
yield break;
bool afterSelf = false;
foreach (var child in item.Ancestors().First().Elements())
{
if (afterSelf)
yield return child;
if (child.Equals(item))
afterSelf = true;
}
}
/// <summary>
/// Returns a collection containing this element and all child elements.
/// </summary>
public static IEnumerable<DependencyObject> ElementsAndSelf(this DependencyObject item)
{
yield return item;
foreach (var child in item.Elements())
{
yield return child;
}
}
/// <summary>
/// Returns a collection of descendant elements which match the given type.
/// </summary>
public static IEnumerable<DependencyObject> Descendants<T>(this DependencyObject item)
{
return item.Descendants().Where(i => i is T).Cast<DependencyObject>();
}
/// <summary>
/// Returns a collection of the sibling elements before this node, in document order
/// which match the given type.
/// </summary>
public static IEnumerable<DependencyObject> ElementsBeforeSelf<T>(this DependencyObject item)
{
return item.ElementsBeforeSelf().Where(i => i is T).Cast<DependencyObject>();
}
/// <summary>
/// Returns a collection of the after elements after this node, in document order
/// which match the given type.
/// </summary>
public static IEnumerable<DependencyObject> ElementsAfterSelf<T>(this DependencyObject item)
{
return item.ElementsAfterSelf().Where(i => i is T).Cast<DependencyObject>();
}
/// <summary>
/// Returns a collection containing this element and all descendant elements
/// which match the given type.
/// </summary>
public static IEnumerable<DependencyObject> DescendantsAndSelf<T>(this DependencyObject item)
{
return item.DescendantsAndSelf().Where(i => i is T).Cast<DependencyObject>();
}
/// <summary>
/// Returns a collection of ancestor elements which match the given type.
/// </summary>
public static IEnumerable<DependencyObject> Ancestors<T>(this DependencyObject item)
{
return item.Ancestors().Where(i => i is T).Cast<DependencyObject>();
}
/// <summary>
/// Returns a collection containing this element and all ancestor elements
/// which match the given type.
/// </summary>
public static IEnumerable<DependencyObject> AncestorsAndSelf<T>(this DependencyObject item)
{
return item.AncestorsAndSelf().Where(i => i is T).Cast<DependencyObject>();
}
/// <summary>
/// Returns a collection of child elements which match the given type.
/// </summary>
public static IEnumerable<DependencyObject> Elements<T>(this DependencyObject item)
{
return item.Elements().Where(i => i is T).Cast<DependencyObject>();
}
/// <summary>
/// Returns a collection containing this element and all child elements.
/// which match the given type.
/// </summary>
public static IEnumerable<DependencyObject> ElementsAndSelf<T>(this DependencyObject item)
{
return item.ElementsAndSelf().Where(i => i is T).Cast<DependencyObject>();
}
}
public static class EnumerableTreeExtensions
{
/// <summary>
/// Applies the given function to each of the items in the supplied
/// IEnumerable.
/// </summary>
private static IEnumerable<DependencyObject> DrillDown(this IEnumerable<DependencyObject> items,
Func<DependencyObject, IEnumerable<DependencyObject>> function)
{
foreach (var item in items)
{
foreach (var itemChild in function(item))
{
yield return itemChild;
}
}
}
/// <summary>
/// Applies the given function to each of the items in the supplied
/// IEnumerable, which match the given type.
/// </summary>
public static IEnumerable<DependencyObject> DrillDown<T>(this IEnumerable<DependencyObject> items,
Func<DependencyObject, IEnumerable<DependencyObject>> function)
where T : DependencyObject
{
foreach (var item in items)
{
foreach (var itemChild in function(item))
{
if (itemChild is T)
{
yield return (T)itemChild;
}
}
}
}
/// <summary>
/// Returns a collection of descendant elements.
/// </summary>
public static IEnumerable<DependencyObject> Descendants(this IEnumerable<DependencyObject> items)
{
return items.DrillDown(i => i.Descendants());
}
/// <summary>
/// Returns a collection containing this element and all descendant elements.
/// </summary>
public static IEnumerable<DependencyObject> DescendantsAndSelf(this IEnumerable<DependencyObject> items)
{
return items.DrillDown(i => i.DescendantsAndSelf());
}
/// <summary>
/// Returns a collection of ancestor elements.
/// </summary>
public static IEnumerable<DependencyObject> Ancestors(this IEnumerable<DependencyObject> items)
{
return items.DrillDown(i => i.Ancestors());
}
/// <summary>
/// Returns a collection containing this element and all ancestor elements.
/// </summary>
public static IEnumerable<DependencyObject> AncestorsAndSelf(this IEnumerable<DependencyObject> items)
{
return items.DrillDown(i => i.AncestorsAndSelf());
}
/// <summary>
/// Returns a collection of child elements.
/// </summary>
public static IEnumerable<DependencyObject> Elements(this IEnumerable<DependencyObject> items)
{
return items.DrillDown(i => i.Elements());
}
/// <summary>
/// Returns a collection containing this element and all child elements.
/// </summary>
public static IEnumerable<DependencyObject> ElementsAndSelf(this IEnumerable<DependencyObject> items)
{
return items.DrillDown(i => i.ElementsAndSelf());
}
/// <summary>
/// Returns a collection of descendant elements which match the given type.
/// </summary>
public static IEnumerable<DependencyObject> Descendants<T>(this IEnumerable<DependencyObject> items)
where T : DependencyObject
{
return items.DrillDown<T>(i => i.Descendants());
}
/// <summary>
/// Returns a collection containing this element and all descendant elements.
/// which match the given type.
/// </summary>
public static IEnumerable<DependencyObject> DescendantsAndSelf<T>(this IEnumerable<DependencyObject> items)
where T : DependencyObject
{
return items.DrillDown<T>(i => i.DescendantsAndSelf());
}
/// <summary>
/// Returns a collection of ancestor elements which match the given type.
/// </summary>
public static IEnumerable<DependencyObject> Ancestors<T>(this IEnumerable<DependencyObject> items)
where T : DependencyObject
{
return items.DrillDown<T>(i => i.Ancestors());
}
/// <summary>
/// Returns a collection containing this element and all ancestor elements.
/// which match the given type.
/// </summary>
public static IEnumerable<DependencyObject> AncestorsAndSelf<T>(this IEnumerable<DependencyObject> items)
where T : DependencyObject
{
return items.DrillDown<T>(i => i.AncestorsAndSelf());
}
/// <summary>
/// Returns a collection of child elements which match the given type.
/// </summary>
public static IEnumerable<DependencyObject> Elements<T>(this IEnumerable<DependencyObject> items)
where T : DependencyObject
{
return items.DrillDown<T>(i => i.Elements());
}
/// <summary>
/// Returns a collection containing this element and all child elements.
/// which match the given type.
/// </summary>
public static IEnumerable<DependencyObject> ElementsAndSelf<T>(this IEnumerable<DependencyObject> items)
where T : DependencyObject
{
return items.DrillDown<T>(i => i.ElementsAndSelf());
}
}
}
Regards, Colin E.
Tags: codeproject, linq, silverlight, t4, templates, WPF


email: ceberhardt@scottlogic.co.uk
on Google+





[...] LinqToVisualTree a nuestro [...]
We can’t convert the project into visual studio 2010, we are using visual studio 2010 express, then what a steps to convert the project
I don’t really have time to trouble-shoot problems from people commenting on my blog. I would suggest that you ask a question on stackoverflow.com – you will often get an answer very quickly from that site.
[...] trying to find an answer to this question and I stumbled across something called LinqToVisualTree (http://www.scottlogic.co.uk/blog/colin/2010/03/linq-to-visual-tree/) this allows me to tap into the Linq namespace and easily reference objects from other classes. To [...]
Thanks a lot – this is magic! I love linq and have a million different helpers scattered around my apps that walk the trees. This approach beautified my code and gives me a consistent solution. I’m inspired to write my first StackOverflow article using my own helper class with yours backing it up!!!
[...] trying to find an answer to this question and I stumbled across something called LinqToVisualTree (http://www.scottlogic.co.uk/blog/colin/2010/03/linq-to-visual-tree/) this allows me to tap into the Linq namespace and easily reference objects from other [...]
Very nice work but I’ve encountered a problem.
When working with ContentPresenter or ScrollContentPresenter when I enumerate through the controls and hit these guys I get 0 child controls present. This inspite of the fact that I have 30 or so controls bound to the content.
Any suggestions?
Thanks, I’ll look into this. Sounds easy to fix.
[...] the selector in the AnimationsComplete() method. But before I show you the code, you’ll need ‘Linq to Visual Tree’ by Colin Eberhardt. The code file is already included in the demo app. Now you’ve got the necessary code, you [...]
Man, this is the kind of stuff that should be already inside .NET Framework! Congrats! This is awesome!
[...] uses the LinqToVisualTree helper by @ColinEberhardt to find the next TextBox or PasswordBox after the AssociatedObject. If it [...]
Excellent!
[...] was topmost ancestor having specified DataContext. Google gave me a cool reference to people doing Linq2VisualTree: Having slightly adapted, my code become very clear: var parentScreen = [...]
Thank you Colin, brilliant work!
We have dropped our multiple finders/utilities/helpers.
Let me suggest one enhancement: please cast templated extensions like this:
public static IEnumerable Ancestors(this DependencyObject item) where T : DependencyObject
{
return item.Ancestors().Where(i => i is T).Cast();
}
It will give opportunity to reduce custom code:
compare this —-
var parentScreen = this.Ancestors().Where(d => d.DataContext is Screen).Last();
and this ——
var parentScreen = (FrameworkElement) this.Ancestors().Where(d => d is FrameworkElement && ((FrameworkElement)d).DataContext is Screen).Last();
[...] had to resort to navigating the visual tree (using Linq to VisualTree) to locate the pan and zoom controls which are added to the chart by default, and remove [...]
[...] I should note, that this code requires the LinqToVisualTree library found and explained @ http://www.scottlogic.co.uk/blog/colin/2010/03/linq-to-visual-tree/ [...]
I think the Silverlight Toolkit comes with that stuff already. There are extension methods like .GetVisualDescendants() etc…
The extension methods are defined in System.Windows.Controls.Toolkit in the namespace System.Windows.Controls.Primitives.
[...] GetScrollBar method is invoked, which then uses Linq-to-VisualTree to walk the descendants of the ScrollViewer in an attempt to find scrollbars of a given [...]
Thanks for the interesting article.
I would suggest updating the code in the text area as it doesn’t compile.
@Quintin,
Thanks for pointing that out – the pesky HTML filter had removed all my angle brackets! It should work now.
Colin E.
[...] Linq to Visual Tree (Colin Eberhardt) [...]
Great stuff. I’m sure I’ll end up using this all over the place.
@Phil, @brad … thanks – glad you liked it
Nice work. Excellent use of Extension Methods.
Linq to Visual Tree | Colin Eberhardt’s Adventures in WPF…
Thank you for submitting this cool story – Trackback from iAwaaz-News-for-the-People-by-the-People…