Locations

Blog Stats

Archive for the ‘LINQ to Visual Tree’ Category

Introduction

This post presents an early prototype of ‘LINQ to Visual Tree’ for Silverlight 2 and WPF applications. The ultimate goal is to provide applications with the ability to quickly and easily query the Silverlight 2 or WPF Visual Tree via LINQ to Objects.

The prototype provides this functionality by enabling enumeration of an application’s in-memory Visual Tree through the IEnumerable<T> interface. This is distinct to implementing a custom query provider: the prototype does not implement IQueryable<T> or execute and translate expression trees.

This post demonstrates the basics so far and makes the prototype available for download, it’s aim is to get feedback and ideas on how the simple API can be improved.

Trees in Silverlight and WPF

The one fundamental tree of objects that make up a Silverlight 2 or WPF application is the object tree. WPF provides two conceptual views of the object tree called the logical tree and the visual tree that if combined would expose the full object tree. The two conceptual trees are exposed via the LogicalTreeHelper and VisualTreeHelper static classes respectively. The logical tree is a map of elements in the object tree’s element hierarchy (defined in Xaml or in code) that make up an applications user interface, including inferred elements not explicitly typed by the programmer. The visual tree is a map of elements in the object tree’s element hierarchy that derive from Visual or Visual3D, each element is exploded into it’s constituent visual ingredient elements.

Silverlight does not expose the full object tree, there is more than likely a logical tree behind the scenes but there is currently no LogicalTreeHelper static class to expose it. Silverlight does however expose a visual tree through VisualTreeHelper but the Visual and Visual3D types do not exist in the API. The criteria for an object’s inclusion in the Silverlight visual tree according to MSDN is that the object has a "rendering implication".

LINQ to Visual Tree

So every Silverlight and WPF application has a Visual Tree exposed through VisualTreeHelper. ‘LINQ to Visual Tree’ extends this model by enabling enumeration of the results returned from VisualTreeHelper for an object and it’s descendants. The prototype is exactly two days old – I’m still experimenting at this stage, it currently consists of the following two extension methods:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Windows;

using System.Windows.Media;

namespace LinqToVisualTree.Common

{

publicstaticclassVisualEnumerable

{

///<summary>

/// Gets the Visual Tree filtered by Type for a DependencyObject with that DependencyObject as the root.

Although there are currently only two extension methods, they provide an abundance of scope for querying the Visual Tree in Silverlight or WPF. Let’s take a look at some usage scenarios from the code download to see how ‘LINQ to Visual Tree’ can be used in practice to query the Visual Tree of a Silverlight 2 application consisting of the following simple Xaml:

Xaml similar to the above is also used for the test WPF application in the code download, for testing it’s really the hierarchy of the elements in the Xaml that is important – this can be visualized as follows:

The code download defines seven tasks that demonstrate how to use the ‘LINQ to Visual Tree’ API, starting off with basic queries and progressing to slightly more involved ones. Each task shows the code to produce the required result using both Extension Method syntax and LINQ syntax. Each task is represented by a method called from the Page_Loaded event handler defined in the above Xaml:

///<summary>

/// Task 1: Get the Visual Tree of this UserControl

///</summary>

privatevoid Task1()

{

// Extension Method syntax

var pageTree1 = this.GetVisualTree();

// Linq syntax

var pageTree2 = from v inthis.GetVisualTree()

select v;

Debug.Assert(pageTree1.SequenceEqual(pageTree2));

}

Silverlight Result

WPF Result

///<summary>

/// Task 2: Get all the TextBox controls in this UserControl's Visual Tree

Feel free to download the code and run the tasks to see how the API is used from both Silverlight and WPF. As I say I’m still experimenting with this so I’d love to hear your suggestions and get feedback and ideas on how the simple API can be improved.