Как использовать TreeView.Resources HierarchicalDataTemplate DataType, чтобы указать словарь<строка, список <T >>?

У меня есть список OBJs, которые я сохранил в List<OBJ> OBJS собственность, и я создал HierarchicalDataTemplate для данных, которые работают (см. ниже).

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

Что дало мне ниже TreeView:

  • Снаряд А
  • Снаряд Б
  • Снаряд С
  • Частица А
  • Частица Б
  • Частица С

Тем не менее, потому что мои данные на самом деле List из OBJесть дочерние классы, которые находятся в том же списке, я хотел сгруппировать классы под своим собственным Type, т.е. new List<OBJ>() { new Projectiles(), new Particles() } должен иметь узел для Projectiles, Particlesи т. д. Я создал 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, создавая соответствующие группы:

  • снаряды
  • Частицы

Но расширение их дало бы мне следующие две ошибки для каждого узла внутри Particles или же Projectiles,

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игнорирует все DataTemplates что вы определили в TreeView.Resources?

В моей первой попытке я смог использовать 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>

Таким образом, в итоге у меня будет следующее:

  • снаряды
    • Снаряд А
    • Снаряд Б
    • Снаряд С
  • Частицы
    • Частица А
    • Частица Б
    • Частица С

Изменить: Это также должно работать, если у меня есть подуровни, см. Ниже.

  • снаряды
    • Снаряд СубТип А
      • Снаряд А
    • Снаряд SubType B
      • Снаряд Б
      • Снаряд С
  • Частицы
    • Частица А
    • Частица Б
    • Частица С

1 ответ

Попробуй это:

<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;
Другие вопросы по тегам