一个用于多个类似HierarchicalDataTemplate-s的模板?

问题描述

我有一个TreeView组件,它可以包含几种类型的节点。一切正常,除了我有多个层次结构数据模板,它们只是在它们显示的字形图像,DataType和ItemsSource上有所不同,但其他所有内容都完全相同。

我想知道,是否可以为所有分层数据模板创建一个ControlTemplate并通过使用tag属性修改图标图像?

例如,我有基本的TreeNode类和从TreeNode继承的节点,如PersonNode,PropertyNode,StreetNode。 TreeNode显示文件夹图标,PersonNode显示用户图标,PropertyNode显示房屋图标,StreeNode显示街道图标。 因此,实际上它们都具有相同的内容结构,只是图标,DataType和ItemsSource正在更改。

如何简化分层数据模板?

示例代码

 <HierarchicalDataTemplate
    DataType="{x:Type MyTreeFolder:TreeNode}"
    ItemsSource="{Binding Path=Items}">
    
    <StackPanel Orientation="Horizontal">
        <StackPanel.Style>
            <Style targettype="StackPanel">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=IsspecialNode}" Value="True">
                        <Setter Property="Background" Value="Blue"></Setter>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </StackPanel.Style>

        <glyphs:GlyphAwesome 
            FontSize="12"
            Glyph="folder"
            Margin="0,4,0"
            VerticalAlignment="Center"/>

        <TextBlock Text="{Binding}" VerticalAlignment="Center"/>
                
    </StackPanel>
    
</HierarchicalDataTemplate>

解决方法

您可以创建一个值转换器,该值转换器检查树节点的类型并返回字形文本。类型到字形文本的映射可以存储在字典中。

public class ObjectTypeToGlyphConverter : IValueConverter
{
   private static readonly IDictionary<Type,string> TypeToGlyphMapping = new Dictionary<Type,string>
   {
      [typeof(TreeNode)] = "folder",[typeof(PersonNode)] = "person",[typeof(PropertyNode)] = "property"
   };

   public object Convert(object value,Type targetType,object parameter,CultureInfo culture)
   {
      var type = value?.GetType();
      return type != null && TypeToGlyphMapping.TryGetValue(type,out var glyph) ? glyph : null;
   }

   public object ConvertBack(object value,CultureInfo culture)
   {
      throw new InvalidOperationException();
   }
}

您需要在范围内的资源字典中创建此转换器的实例,例如:

<TreeView ItemsSource="{Binding TreeNodes}">
   <TreeView.Resources>
      <local:ObjectTypeToGlyphConverter x:Key="ObjectTypeToGlyphConverter"/>
   </TreeView.Resources>
   <!-- ...tree view definitions. -->
</TreeView>

然后您可以像这样在分层数据模板的GlyphAwesome中使用它。

<glyphs:GlyphAwesome FontSize="12"
                     Glyph="{Binding Converter={StaticResource ObjectTypeToGlyphConverter}}"
                     Margin="0,4,0"
                     VerticalAlignment="Center"/>

在这种情况下,TreeNode类型只需要一个数据模板,因为正如您所说的那样,所有节点类型基本上都是相同的,除了图标之外,没有其他特殊处理。