I have a MVVM WPF application with a tree containing self referenced data, this data is bound to the tree with a hierarchical converter. (As in example: http://www.telerik.com/h
If your ItemsSource
is made up of different Types, then you can simply create HierarchicalDataTemplates
and not assign an x:Key. If there is no x:Key attribute for a DataTemplate
, the framework will use this DataTemplate
when it comes across the type and tries to visually display it (you can read more about implicit DataTemplates
here). For example, if you have a type Circle and another type Square, you would have the following templates in your Resources:
<Window.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Circle}" ItemsSource="{Binding Children}">
<Ellipse Fill="{Binding Fill}" Width="25" Height="25" Stroke="Black" StrokeThickness="0.25"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:Square}" ItemsSource="{Binding Children}">
<Rectangle Fill="{Binding Fill}" Width="25" Height="25" Stroke="Black" StrokeThickness="0.25"/>
</HierarchicalDataTemplate>
</Window.Resources>
Then if your TreeView
encounters one of these Types in its ItemsSource
, it will use the HierarchicalDataTemplate
for that specific type.
You can read more about HierarchicalDataTemplates
here, and this link has an example of how they are used in a TreeView
.
OR
If your items are all the same Type, and only differentiated by a property (such as Type), you'll need to use a DataTemplateSelector
. Here is a simple example of one:
codebehind:
public class ShapeTemplateSelector : DataTemplateSelector
{
public DataTemplate CircleTemplate { get; set; }
public DataTemplate SquareTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
Shape shape = item as Shape;
if (shape != null)
{
if (shape.Type == "Circle")
return this.CircleTemplate;
else if (shape.Type == "Square")
return this.SquareTemplate;
}
return null;
}
}
And XAML:
<local:ShapeTemplateSelector x:Key="shapeSelector">
<local:ShapeTemplateSelector.CircleTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:Shape}" ItemsSource="{Binding Children}">
<Ellipse Fill="{Binding Fill}" Width="25" Height="25" Stroke="Black" StrokeThickness="0.25"/>
</HierarchicalDataTemplate>
</local:ShapeTemplateSelector.CircleTemplate>
<local:ShapeTemplateSelector.SquareTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:Shape}" ItemsSource="{Binding Children}">
<Rectangle Fill="{Binding Fill}" Width="25" Height="25" Stroke="Black" StrokeThickness="0.25"/>
</HierarchicalDataTemplate>
</local:ShapeTemplateSelector.SquareTemplate>
</local:ShapeTemplateSelector>
Then in your TreeView
, you simply assign the selector
<TreeView x:Name="Tree" ItemsSource="{Binding Shapes}" ItemTemplateSelector="{DynamicResource shapeSelector}"/>
If you have actual different types, you can specify the type in the HierarchicalDataTemplate using DataType attribute (How do I use the DataType property on a WPF DataTemplate?) and WPF will select the template based on the class.
If you don't have different types, but will depend on a property or value inside the class, you'll need to specify a DataTemplateSelector (http://tech.pro/tutorial/807/wpf-tutorial-how-to-use-a-datatemplateselector)