I've looked at the similar questions regarding TreeView data binding to nested collections, and I've read several "Josh 'n Bea" articles about this topic, but my design differs in that i have "static" TreeViewItems
that serve as collapsible containers fo开发者_C百科r the nested collection items. It's best to illustrate what I'm looking for.
Given these ViewModel classes:
namespace TreeViewSample
{
public class ApplicationViewModel
{
public ApplicationViewModel() { Projects = new List<ProjectViewModel>(); }
public IEnumerable<ProjectViewModel> Projects { get; set; }
}
public class ProjectViewModel
{
public ProjectViewModel() { Maps = new List<MapViewModel>(); }
public string Name { get; set; }
public IEnumerable<MapViewModel> Maps { get; set; }
}
public class MapViewModel
{
public MapViewModel() { Tables = new List<TableViewModel>(); }
public string Name { get; set; }
public IEnumerable<TableViewModel> Tables { get; set; }
}
public class TableViewModel
{
public TableViewModel() { Fields = new List<FieldViewModel>(); }
public string Name { get; set; }
public IEnumerable<FieldViewModel> Fields { get; set; }
}
public class FieldViewModel
{
public string Name { get; set; }
}
}
This is the result i want:
Can anyone help me with the XAML for this TreeView? I thought i understood how HierarchicalDataTemplates
work, but the "static" container nodes ("Tables", "Fields", "Maps") seem to confuse me.
Thank you and have a pleasant day!
I think you're gonna have to create HierarchicalDataTemplate
s for the "Static" nodes as well. And since ItemsSource of an HierarchicalDataTemplate
expects a Collection you can create these collections in Xaml like this
Namespaces
xmlns:coll="clr-namespace:System.Collections;assembly=mscorlib"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Collections
<coll:ArrayList x:Key="MapCollection">
<sys:String>Maps</sys:String>
</coll:ArrayList>
<coll:ArrayList x:Key="TableCollection">
<sys:String>Tables</sys:String>
</coll:ArrayList>
<coll:ArrayList x:Key="FieldCollection">
<sys:String>Fields</sys:String>
</coll:ArrayList>
The problem with this solution is that when you set e.g. MapCollection as ItemsSource for a HierarchicalDataTemplate
, you won't have access to the Maps
Collection Property in the next level so you'll have to climb up the Visual Tree to get a hold of it like
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}},
Path=DataContext.Maps}"
Using this approach, your HierarchicalDataTemplate
s can look like this
<!-- Field Templates -->
<HierarchicalDataTemplate x:Key="FieldsTemplate">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="FieldTemplate"
ItemTemplate="{StaticResource FieldsTemplate}"
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}},
Path=DataContext.Fields}">
<TextBlock Text="{Binding}"/>
</HierarchicalDataTemplate>
<!-- Table Templates -->
<HierarchicalDataTemplate x:Key="TablesTemplate"
ItemTemplate="{StaticResource FieldTemplate}"
ItemsSource="{Binding Source={StaticResource FieldCollection}}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="TableTemplate"
ItemTemplate="{StaticResource TablesTemplate}"
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}},
Path=DataContext.Tables}">
<TextBlock Text="{Binding}"/>
</HierarchicalDataTemplate>
<!-- Map Templates -->
<HierarchicalDataTemplate x:Key="MapsTemplate"
ItemTemplate="{StaticResource TableTemplate}"
ItemsSource="{Binding Source={StaticResource TableCollection}}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="MapTemplate"
ItemTemplate="{StaticResource MapsTemplate}"
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}},
Path=DataContext.Maps}">
<TextBlock Text="{Binding}"/>
</HierarchicalDataTemplate>
<!-- Project Template -->
<HierarchicalDataTemplate x:Key="ProjectDataTemplate"
ItemTemplate="{StaticResource MapTemplate}"
ItemsSource="{Binding Source={StaticResource MapCollection}}">
<TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>
TreeView
<TreeView Name="treeView"
ItemTemplate="{StaticResource ProjectDataTemplate}"
ItemsSource="{Binding Projects}"/>
精彩评论