WPF Tree Datatemplate Depending on Type of Item

前端 未结 2 1410
后悔当初
后悔当初 2021-01-22 20:59

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

相关标签:
2条回答
  • 2021-01-22 21:12

    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}"/>
    
    0 讨论(0)
  • 2021-01-22 21:12

    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)

    0 讨论(0)
提交回复
热议问题