加入 TreeView 的集合

Join collections for TreeView

我有一个名为 LogEntry 的 class,其定义如下:

public class LogEntry
{
   public LogEntry()
   {
      Children = new List<LogEntry>();
   }

   public string Name { get; set; }

   public int Id { get; set; }

   public List<LogEntry> Children { get; private set; }

   public override ToString()
   {
      return Name;
   }       
}

通过我的应用程序的界面,我得到了 LogEntries 的列表,例如

root -> sub1 -> subsub11 -> value111
root -> sub1 -> subsub11 -> value112
root -> sub1 -> subsub12 -> value121
root -> sub1 -> subsub12 -> value122
root -> sub1 -> subsub13 -> value131
root -> sub2 -> subsub21 -> value221
root -> sub3 -> subsub31 -> value331
root -> sub1 -> subsub12 -> value123

-> 显示当前 LogEntry 的子集合中的唯一子。

现在我想在 TreeViewHierarchicalDataTemplate 中显示它。如果我使用以下 TreeView-定义将集合直接传递给 TreeView

<TreeView ItemsSource="{Binding HierarchicalLogEntries, UpdateSourceTrigger=PropertyChanged}">
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type model:LogEntry}" ItemsSource="{Binding Children}">
            <TextBlock Text="{Binding Name}"/>
        </HierarchicalDataTemplate>
    </TreeView.Resources>
</TreeView>

有了这个,每个 LogEntry 都显示为一个节点。我有 8 个具有相同文本的根节点。

我现在的问题是:是否有一种简单的方法可以将这些对象连接在一起,以便我只有一个根元素并且所有子元素也将被匹配?

正如我在评论中提到的,您应该手动分组/加入您的条目。

这是一个示例,您可以如何使用 linq 的 GroupBy() 和递归调用的方法来执行此操作。请注意,这只是一个示例,并非最佳方法。

假设您有一个输入集合 IEnumerable<LogEntry> entries 来保存您所描述的 'plain' 数据,您可以这样做:

this.HierarchicalLogEntries.AddRange(this.Group(entries));

Group() 方法可能如下所示:

IEnumerable<LogEntry> Group(IEnumerable<LogEntry> entries)
{
    List<LogEntry> result = new List<LogEntry>();

    var groups = entries.GroupBy(e => e.Id);
    foreach (var group in groups)
    {
        var children = group.SelectMany(e => e.Children);
        if (children.Any())
        {
            var key = group.First();
            LogEntry newItem = new LogEntry { Id = key.Id, Name = key.Name };
            newItem.Children.AddRange(Group(children));
            result.Add(newItem);
        }
        else
        {
            result.AddRange(group);
        }
    }

    return result;
}