Группировка дочерних объектов в WPF TreeView - PullRequest
7 голосов
/ 12 февраля 2010

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

  • Объекты
    • Группа объектов № 1
      • Элемент № 1 (тип «А»)
      • Элемент № 2 (тип «А»)
      • Элемент № 3 (тип «B»)
      • Элемент № 4 (тип «B»)

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

  • Объекты
    • Группа объектов № 1
      • Тип А
        • Элемент № 1
        • Элемент № 2
      • Тип Б
        • № позиции 3
        • № позиции 4

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

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

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

Ответы [ 4 ]

7 голосов
/ 12 февраля 2010

Вы можете добиться этого эффекта, привязав 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>
5 голосов
/ 12 февраля 2010

Взгляните на эту статью мистера Суми. Я уверен, что это поможет вам.

0 голосов
/ 16 июня 2015

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

<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}"
... />
0 голосов
/ 12 февраля 2010

AFAIK, HierarchicalDataTemplate не может группировать своих детей.

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

И вид просто получит что-то вроде:

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

и отобразите его, используя HierarchicalDataTemplate.

...