In my previous post I showed how to take an ordinary TreeView and turn it into an org chart-like control complete with connection lines between nodes. However, it was those darn connection lines that are the crux of the issues requiring the refactor.
Take a look at the original data template:
See that fat comment before the Border declaration? It made me sick. You see, when we draw connection lines we don’t draw them between TreeViewItems, we draw them between the visuals representing our Node object, which in this case begins with a Border, but in the case of some other UI designer could end up being any ole’ thing.
Now take a look at the code used to find that border:
Do you see it? Right there under the comment that reads ” //when we’ve found one, we need to find the main visual underneath the content “. A hardcoded navigation under the visual tree of the TreeViewItem to find that specific Border we identified in the DataTemplate previously showed above.
…Disgusting. What would happen if some UI designer wanted to use a StackPanel or a Grid or heck even a Button as the basis for the style of our Node or embedded the node deeper in the visual tree by nesting elements? That’s right, we’d have to come in here and modify this code to find the appropriate element to calculate the location of. After posting the original entry, I went to sleep and the thought of this haunted me and made my skin crawl. It was late and my brain was tired so I couldn’t fathom how I was going to allow a designer to specify what the appropriate element for a node was and how I would then go about identifying it more generically so that I’d never again have to revisit that particular aspect of the code. Just as I started to drift off to uneasy sleep it hit me…
Duh - attached properties! That’s what they’re for in case you don’t know. You can create a property on some parent element that it’s children can use to pass information back into the parent. They’re called “attached” properties because you can attach them to any ole’ thing. StackPanel, Grid, Button, it don’t matter. That’s how attached properties roll, baby! So I sat up in bed and pulled back out the trusty computer to fix things up proper.
Attached Properties to the Rescue
So how do you write and use an attached property? The long answer is here, at the MSDN Attached Properties Overview page which is the way you’ll go if you’re not coding in Visual Studio. The short answer is, why write them out when you can use a code snippet to do it for you, like the excellent collection provided by Dr. WPF. Thanks Doc!
So that, being said, we simply add an attached property to our original OrgChartTreeView class called IsVisualNode to be set by any element under a TreeViewItem that is the visual representation of our node object.
Now a UI designer working in XAML can change our data template to look like this:
No need for a lame disclaimer now. We simply tell the UI Designer to set the following attached property on the Border: local:OrgChartTreeView.IsVisualNode=”True” as you can see has been done above.
No need to limit yourself to the Border, you could put it on the TextBlock or the ContentPresenter in the TreeViewItem control template, basically anything under the TreeViewItem.
Now we simply refactor our GetTreeViewItemLocations method from this:
…to this…
…and add the following helper method to find the FrameWorkElement that is using our attached property:
Now we can let UI Designers decide how they want to make a Node look and the control will still function correctly so long as they tell us through our attached property which element we need to be connecting as nodes. And more importantly I can sleep at night.
One More Refactor
If you recall the output from the previous post, our Org Chart looked like this:
Nothing wrong there. You can see that our connection lines go from the center of the visual representation of our parent node (the Border), to the center of the child node’s Border. What if we want the connection to go from the bottom of the parent, the to top of the child? What if we want to support both scenarios and let the UI Designer decide? Attached properties again? Nah, this time we want a regular ole dependency property, not set on a child item, but rather on the main parent element itself. Here’s the Microsoft overview of dependency properties. I, for one, will be using my handy dandy code snippets again to create the following boolean DP:
Now in our GetTreeViewItemLocations method, instead of attaching Point data to the internal node data, we can just attach the whole visual element like so:
Why store the element instead of the location Point? So that we can do this when we draw the connectors:
See how we set the location points dynamically based on the value of the dependency property? We either get the point in the center of the element, or we get the bottom center point of the parent and the top center point of the child to draw a line between. We use the following helper methods to get the various points:
Now when a designer sets the property in XAML:
We get the original output again:

versus the following subtley different output when the property is set to false or just not there:
Here’s the updated source code.
And that’s all I have to say about that. You have a nice day.

June 30th, 2008 at 3:04 pm
[...] 30, 2008 managed to port the solution from http://wpfblog.info/2008/05/27/wpf-treeview-org-chart-a-bit-of-refactoring/ and combine with the previous solution. Posted by ahmylife Filed in role management Tags: gui, [...]
July 1st, 2008 at 1:49 pm
Dear Sir,
Thank you for nice example.I am new to WPF. How to add abitily so that user can navigate through treeview (adding nodeselected/click events)? I am trying to use dataset to populate treeview. Also how to add soft scroll to nodes?
Hope to hear from you soon.
Thank you
Nitin