如何使用TreeView.Resources层次结构数据模板DataType指定字典<;字符串,列表<;T>

本文关键字:lt 字符串 字典 gt 列表 Resources TreeView 何使用 层次结构 数据 DataType | 更新日期: 2023-09-27 18:20:58

我有一个OBJ列表,我已经将其存储在List<OBJ> OBJS属性中,并且我已经为Data创建了一个HierarchicalDataTemplate,它可以工作(见下文)。

 <TreeView.Resources>
      <HierarchicalDataTemplate DataType="{x:Type EntityType:Projectiles}" 
                                ItemsSource="{Binding Value}">
           <TextBlock Text="{Binding RelativeSource={RelativeSource Self},
                      Converter={StaticResource NameConverter}}"/>
      </HierarchicalDataTemplate>
 </TreeView.Resources>

这给了我以下树视图:

  • 炮弹A
  • 炮弹B
  • 弹丸C
  • 颗粒A
  • 颗粒B
  • 颗粒C

然而,因为我的数据实际上是OBJList,所以在同一列表中有子类,所以我想将这些类分组到它自己的Type下。即new List<OBJ>() { new Projectiles(), new Particles() }应该有一个节点用于ProjectilesParticles等。我创建了一个Converter,它将其更改为Dictionary,然后它就不能与上面的HierarchicalDataTemplate一起工作,因为它现在是Dictionary<string, List<OBJ>

然后,我创建了一个新的HierarchicalDataTemplate来处理Dictionary<string, List<OBJ>,请参见下文。

 <TreeView Name="MyTreeView" ItemsSource="{Binding OBJS, 
           Converter={StaticResource ItemsSourceConverter}}"
 <TreeView.ItemTemplate>
      <HierarchicalDataTemplate ItemsSource="{Binding Value}">
           <TextBlock Text="{Binding Key}" />
      </HierarchicalDataTemplate>
 </TreeView.ItemTemplate>

Converter:

 class ItemsSourceConverter : IValueConverter {
      public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
           List<OBJ> objs = new List<OBJ>(value as List<OBJ>);
           var query = (from a in objs
                          group a by a.GetType() into b
                          select new {
                               EntityName = b.Key.ToString().Split('.').Last().Substring(0,1).ToUpper() + b.Key.ToString().Split('.').Last().Substring(1).ToLower(),
                               Entities = b.OrderBy(a=>a.retrieveName()).ToList()
                          }).ToDictionary(kvp => kvp.EntityName, kvp => kvp.Entities);
           return query;
      }
      public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
           return null;
      }
 }

这给了我下面的TreeView,创建了合适的组:

  • 射弹
  • 粒子

但是扩展它们会使我对ParticlesProjectiles中的每个节点都产生以下两个错误。

System.Windows.Data Error: 40 : BindingExpression path error: 'Value' property not found on 'object' 'Projectiles' (HashCode=37857370)'. BindingExpression:Path=Value; DataItem='Projectiles' (HashCode=37857370); target element is 'TreeViewItem' (Name=''); target property is 'ItemsSource' (type 'IEnumerable') System.Windows.Data Error: 40 : BindingExpression path error: 'Key' property not found on 'object' 'Projectiles' (HashCode=37857370)'. BindingExpression:Path=Key; DataItem='Projectiles' (HashCode=37857370); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

似乎一旦您设置了TreeView.ItemTemplate,它就会忽略您在TreeView.Resources中定义的所有DataTemplates

在我的第一次尝试中,我能够使用DataType="{x:Type EntityType:Projectiles}"来指定我希望HierarchicalDataTemplate用于Projectiles对象,是否有DataType语法可以让我指定DataType="{x:Type Dictionary<string, List<OBJ>>}"?所以我可以做下面这样的事情?

 <HierarchicalDataTemplate ItemsSource="{Binding Value}"
                           DataType="{x:Type Dictionary<string, List<OBJ>>}">
      <TextBlock Text="{Binding Key}" />
 </HierarchicalDataTemplate>

这样,最后,我会得到以下内容:

  • 射弹
    • 炮弹A
    • 炮弹B
    • 弹丸C
  • 粒子
    • 颗粒A
    • 颗粒B
    • 颗粒C

编辑:如果我有子级别,这也应该有效,见下文。

  • 射弹
    • A亚型炮弹
      • 炮弹A
    • B亚型炮弹
      • 炮弹B
      • 弹丸C
  • 粒子
    • 颗粒A
    • 颗粒B
    • 颗粒C

如何使用TreeView.Resources层次结构数据模板DataType指定字典<;字符串,列表<;T>

试试这个:

<TreeView Name="treeView1" ItemsSource="{Binding}" >
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Path=Value}">
            <TextBlock FontWeight="Bold" Text="{Binding Path=Key}" />
            <HierarchicalDataTemplate.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}"/>
                </DataTemplate>
            </HierarchicalDataTemplate.ItemTemplate>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

示例类别:

class OBJ
{
    public string Name { get; set; }
}
class Projectiles : OBJ {}
class Particles : OBJ {}

样本数据初始化:

List<OBJ> _source = new List<OBJ>() 
    {
        new Projectiles{ Name = "Projectile A"},
        new Projectiles{ Name = "Projectile B"},
        new Projectiles{ Name = "Projectile C"},
        new Particles { Name = "Particle A"},
        new Particles { Name = "Particle B"},
        new Particles { Name = "Particle C"},
    };
var query = (from a in _source
             group a by a.GetType() into b
             select new
             {
                 EntityName = b.Key.ToString().Split('.').Last().Substring(0, 1).ToUpper() + b.Key.ToString().Split('.').Last().Substring(1).ToLower(),
                 Entities = b.OrderBy(a => a.Name).ToList()
             }).ToDictionary(kvp => kvp.EntityName, kvp => kvp.Entities);
treeView1.DataContext = query;