加入 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
的子集合中的唯一子。
现在我想在 TreeView
和 HierarchicalDataTemplate
中显示它。如果我使用以下 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;
}
我有一个名为 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
的子集合中的唯一子。
现在我想在 TreeView
和 HierarchicalDataTemplate
中显示它。如果我使用以下 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;
}