tags:

views:

2272

answers:

4

I want to be able to traverse the visual ui tree looking for an element with an ID bound to the visual element's Tag property.

I'm wondering how i do this. Controls don't have children to traverse.

I started using LogicalTreeHelper.GetChildren, which seems to work as intended, up until i hit a TreeView control... then LogicalTreeHelper.GetChildren doesnt return any children.

Note: the purpose is to find the visual UI element that corresponds to the data item. That is, given an ID of the item, Go find the UI element displaying it.

Edit: I am apparently am not explaining this well enough. I am binding some data objects to a TreeView control and then wanting to select a specific item programaticly given that business object's ID. I dont see why it's so hard to travers the visual tree and find the element i want, as the data object's ID is in the Tag property of the appropriate visual element. I'm using Mole and I am able to find the UI element with the appropriate ID in it's Tag. I just cannot find the visual element in code. LogicalTreeHelper does not traverse any items in the tree. Neither does ItemContainerGenerator.ContainerFromItem retrieve anything for items in the tree view.

A: 

The problem is that only the TreeViewItems that are visible have been created - WPF does not create all items up front (due to the length of time that could take for large trees, I would imagine).

A better approach would be to create a data structure that mimics the structure of your tree data, and use data binding to tell the TreeView how to display that data. I can write up a simple example, if you'd like.

EDIT: Based on your edit, that will only work if the UI item has been created for that object, which isn't guaranteed. Take a look at the IItemContainerGenerator interface (retrieved by calling ItemsControl.ItemContainerGenerator. I believe that has a method that will return the UI container (i.e. TreeViewItem) for a given data object. That will only work if the UI container has been previously created.

Andy
Based on my work with the TreeView, this is how it works. There is no visual tree up front for tree nodes. These are created on demand as needed. Therefore it is not possible to reliably navigate the "visual tree".
Peter Stephens
A: 

Take a look a this sample. I found this sample very well written and I believe that using view-model will solve your problem.

Edit: And regarding the search of the visual tree. Both TreeView and TreeViewItem have Items property that you can traverse and search for your Id. Can't you use it?

Yuval Peled
The items property are the data items not visual. I can then get the data item and ask for the cooresponding Visual Item, then i need to walk the Visual Item's Items property, which is the data items. This isn't working, I just want to walk the visual tree... so lame
Brian Leahy
A: 

LogicalTreeHelper.GetChildren looks at the control's LogicalChildren property, which is null by default for a TreeView (derived from ItemsControl class). You might have to inspect the type of the objects returned by GetChildren and when you come to a TreeView object, then do some special processing logic.

That special logic will probably be iterating over the tree's Items and trying to cast them to a FrameworkElement (the base class that defines Tag property).

Erich Mirabal
A: 

I have done similar things by recursing through the visual tree using VisualTreeHelper. Check out this blog post written by Jim Baltzell-Gauthier -- it provides some helper methods to walk the visual tree and return an element by name and type, this is similar to the code that I am using on my current project. You could modify these functions to have it check Tag values instead of or in addition to name.

One thing to be aware of with the Visual Tree is that it is not there unless the visuals have been loaded -- you may need to attach a delegate to the "Loaded" event of your visual element if the visual has not been rendered yet at the point that you call the code.

Guy Starbuck