The tricky part of this solution is having to deal with two collections underneath each node and TreeView's HierarchicalDataTemplate only supports binding to a single ItemsSource.
One option is to create a ViewModel that merges the collections into a single class that represents an entry in the TreeView that you can then bind to inside your HierarchicalDataTemplate.
First I created my ViewModel class:
public class TreeViewEntry
{
public string Name { get; set; }
public IEnumerable<TreeViewEntry> Children { get; set; }
public object Model { get; set; }
}
Then I used a function, some Linq and some recursion to pull all the objects into a single collection:
private IEnumerable<TreeViewEntry> OrganizationsToTreeViewEntries(IEnumerable<Organization> orgs)
{
return (from o in orgs
select new TreeViewEntry
{
Name = o.Name,
Model = o,
Children = (from u in o.Users
select new TreeViewEntry
{
Name = u.Name,
Model = u
}
).Concat(OrganizationsToTreeViewEntries(o.Children))
});
}
public MainPage()
{
InitializeComponent();
var items = OrganizationsToTreeViewEntries(existingOrganizationData);
OrgTree.ItemsSource = items;
}
Now that I have a merged ItemsSource it's easy to style my HierarchicalDataTemplate:
<UserControl.Resources>
<common:HierarchicalDataTemplate x:Key="OrgTemplate" ItemsSource="{Binding Children}">
<StackPanel>
<TextBlock Text="{Binding Name}" />
</StackPanel>
</common:HierarchicalDataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource SampleDataSource}}">
<controls:TreeView x:Name="OrgTree" HorizontalAlignment="Left" Margin="8,8,0,8" Width="225" ItemTemplate="{StaticResource OrgTemplate}" />
</Grid>
You can use a ValueConverter to tweaks things like FontWeight if you want to adjust the visual style of certains elements (for example in my testing I created a ValueConverter on FontWeight that was bound to the Model property of TreeViewEntry).