如何使用TreeView.Resources层次结构数据模板DataType指定字典<;字符串,列表<;T>
本文关键字:lt 字符串 字典 gt 列表 Resources TreeView 何使用 层次结构 数据 DataType | 更新日期: 2023-09-27 18:20:58
我有一个OBJ列表,我已经将其存储在List<OBJ> OBJS
属性中,并且我已经为Data创建了一个HierarchicalDataTemplate
,它可以工作(见下文)。
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type EntityType:Projectiles}"
ItemsSource="{Binding Value}">
<TextBlock Text="{Binding RelativeSource={RelativeSource Self},
Converter={StaticResource NameConverter}}"/>
</HierarchicalDataTemplate>
</TreeView.Resources>
这给了我以下树视图:
- 炮弹A
- 炮弹B
- 弹丸C
- 颗粒A
- 颗粒B
- 颗粒C
然而,因为我的数据实际上是OBJ
的List
,所以在同一列表中有子类,所以我想将这些类分组到它自己的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
,它就会忽略您在TreeView.Resources
中定义的所有DataTemplates
?
在我的第一次尝试中,我能够使用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>
这样,最后,我会得到以下内容:
- 射弹
- 炮弹A
- 炮弹B
- 弹丸C
- 粒子
- 颗粒A
- 颗粒B
- 颗粒C
编辑:如果我有子级别,这也应该有效,见下文。
- 射弹
- A亚型炮弹
- 炮弹A
- B亚型炮弹
- 炮弹B
- 弹丸C
- A亚型炮弹
- 粒子
- 颗粒A
- 颗粒B
- 颗粒C
试试这个:
<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;