WPF: Org Chart TreeView Conditional Formatting
Question
The company has the traditional complex organizational structure, defining the amount of levels using the letter 'n' rather than an actual number. I will try and express the structure I'm trying to achieve in mono-spaced font:
Alice
,--------|-------,------,------,
Bob Fred Jack Kim Lucy
| |
Charlie Greg
Darren Henry
Eric
As you can see it's not symmetrical, as Jack, Kim and Lucy report to Alice but have no reports of their own.
Using a TreeView
with an ItemsPanel
containing a StackPanel
and Orientation="Horizontal"
is easy enough, but this can result in a very large TreeView
once some people have 20 others reporting to them! You can also use Triggers
to peek into whether a TreeViewItem
has children with Property="TreeViewItem.HasItems"
, but this is not in the same context as the before-mentioned ItemsPanel
. Eg: I can tell that Fred has reports, but not whether they have reports of their own.
So, can you conditionally format TreeViewItems
to be Vertical if they have no children of their own?
Solution 2
I did end up using tips from the linked article, which I'd already read through but didn't think would help me.
The meat of it happens here, in a converter:
<ValueConversion(GetType(ItemsPresenter), GetType(Orientation))> _
Public Class ItemsPanelOrientationConverter
Implements IValueConverter
Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, _
ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) _
As Object Implements System.Windows.Data.IValueConverter.Convert
'The 'value' argument should reference an ItemsPresenter.'
Dim itemsPresenter As ItemsPresenter = TryCast(value, ItemsPresenter)
If itemsPresenter Is Nothing Then
Return Binding.DoNothing
End If
'The ItemsPresenter''s templated parent should be a TreeViewItem.'
Dim item As TreeViewItem = TryCast(itemsPresenter.TemplatedParent, TreeViewItem)
If item Is Nothing Then
Return Binding.DoNothing
End If
For Each i As Object In item.Items
Dim element As StaffMember = TryCast(i, StaffMember)
If element.IsManager Then
'If this element has children, then return Horizontal'
Return Orientation.Horizontal
End If
Next
'Must be a stub ItemPresenter'
Return Orientation.Vertical
End Function
Which in turn gets consumed in a style I created for the TreeView:
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate >
<ItemsPanelTemplate.Resources>
<local:ItemsPanelOrientationConverter x:Key="conv" />
</ItemsPanelTemplate.Resources>
<StackPanel IsItemsHost="True"
Orientation="{Binding
RelativeSource={x:Static RelativeSource.TemplatedParent},
Converter={StaticResource conv}}" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
OTHER TIPS
Josh Smith has a excecllent CodeProject article about TreeView. Read it here