Сложной частью этого решения является работа с двумя коллекциями под каждым узлом, а TreeView HierarchicalDataTemplate поддерживает только привязку к одному ItemsSource.
Одним из вариантов является создание ViewModel, который объединяет коллекции в единый класс, представляющий запись в TreeView, которую вы затем можете привязать внутри вашего HierarchicalDataTemplate.
Сначала я создал свой класс ViewModel:
public class TreeViewEntry
{
public string Name { get; set; }
public IEnumerable<TreeViewEntry> Children { get; set; }
public object Model { get; set; }
}
Затем я использовал функцию, немного Linq и некоторую рекурсию, чтобы собрать все объекты в одну коллекцию:
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;
}
Теперь, когда у меня есть объединенный ItemSource, можно легко стилизовать мой 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>
Вы можете использовать ValueConverter для настройки таких вещей, как FontWeight, если вы хотите настроить визуальный стиль определенных элементов (например, в моем тестировании я создал ValueConverter для FontWeight, который был привязан к свойству Model TreeViewEntry).