Группировка дочерних объектов в WPF TreeView

Я пытаюсь получить представление дерева, чтобы сгруппировать коллекцию похожих элементов по тому, что они есть. Чтобы сохранить универсальность, моя иерархия объектов может выглядеть так:

  • объекты
    • Группа Объектов #1
      • Пункт #1 (Тип 'A')
      • Пункт #2 (Тип 'A')
      • Пункт #3 (Тип 'B')
      • Пункт #4 (Тип 'B')

прямо сейчас мой TreeView показывает эти объекты точно такие же, как объектная модель, но я хотел бы вставить узел TreeView для каждого типа объекта, чтобы он выглядел так:

  • объекты
    • Группа Объектов #1
      • Тип A
        • пункт #1
        • пункт #2
      • Тип B
        • п. 3
        • пункт #4

Я видел в похожем вопросе вот что кто-то рекомендовал иметь два отдельных HierarchicalDataTemplates поэтому я создал один для уровня "Object Group #1", который содержит TreeView со списком типов, но это действительно неуклюже, так как это целый отдельный TreeView внутри некоторых узлов. Я также пытался использовать CollectionViewSource чтобы отфильтровать элементы в каждой категории, но это не очень хорошо, так как я не могу понять, как их отображать.

Я думаю, мой вопрос сводится к следующему: как я сделайте группа это? Если бы кто-то мог указать мне в правильном направлении, я был бы очень признателен.

Я могу опубликовать некоторый код, если кто-то хочет видеть, но я действительно просто пытаюсь понять, как сделать то, что я хочу, поэтому мой код-это просто довольно прямой treeview базы данных прямо сейчас.

4 ответов


посмотри этой статья г-на Суми. Я уверен, что это вам поможет.


вы можете достичь этого эффекта, связав ItemsSource на HierarchicalDataTempalate С помощью IValueConverter. Этот конвертер просто делает следующее:

public class MyConverter : IValueConverter
{
  public object Convert(object value, ...)
  {
    return
      from item in (IEnumerable<MyItem>)value
      group item by item.Type into g
      select new { Type = item.Type, Items = g };
  }
  ...
}

теперь ваш HierarchcialDataTemplate можно так:

<HierarchicalDataTemplate ItemsSource="{Binding SomePath, Converter={x:Static local:MyConverter}">

  <HierarchicalDataTemplate.ItemTemplate>
    <HierarchicalDataTemplate
      ItemsSource="{Binding Items}"
      TargetType="{x:Type local:MyItem}"

      ItemTemplate="{StaticResource MyItemTemplate}">
         <!-- may omit ItemTemplate in prior line to use implicit template -->

      <TextBlock Text="{Binding Type}" /> <!-- Header for type -->

    </HierarchicalDataTemplate>
  </HierarchicalDataTemplate.ItemTemplate>

  <!-- header for "Object Group #1" -->

</HierarchicalDataTemplate>

насколько я знаю, HierarchicalDataTemplate не удается сгруппировать своих детей.

View должен просто отображать все, что он получает, не копаясь в видах / группах объектов... Почему бы вам не создать эти группы в объектной модели?

и вид будет просто получить smth, как:

public interface ITreeNode
{
    string Title;
    IList<ITreeNode> ChildNodes;  
}

и отобразить его с помощью HierarchicalDataTemplate.


Если это простой метод группировки из плоской коллекции для отображения цели, которую вы ищете, возможно, использование "CollectionViewSource" будет более подходящим. Использование LINQ может стать кошмаром из-за распространения событий изменения свойств/коллекции.

<CollectionViewSource x:Key="GroupedItems" Source="{Binding ItemsSource,  ElementName=My_UserControl}">
    <CollectionViewSource.GroupDescriptions>
        <PropertyGroupDescription PropertyName="Type" Converter="{StaticResource GroupingConverter}" />
    </CollectionViewSource.GroupDescriptions>
    <CollectionViewSource.SortDescriptions>
        <scm:SortDescription PropertyName="Date"/>
    </CollectionViewSource.SortDescriptions>
</CollectionViewSource>

<HierarchicalDataTemplate x:Key="GroupDataTemplate"  ItemsSource="{Binding Items}" >
    <TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>

<TreeView x:Name="ItemHolder" x:FieldModifier="private"
    ItemsSource="{Binding Source={StaticResource GroupedItems}, Path=Groups}"
... />