I have a list of OBJs, that I've stored into List<OBJ> OBJS
property, and I've created a HierarchicalDataTemplate
for the Data, which works (see below).
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type EntityType:Projectiles}"
ItemsSource="{Binding Value}">
<TextBlock Text="{Binding RelativeSource={RelativeSource Self},
Converter={StaticResource NameConverter}}"/>
</HierarchicalDataTemplate>
</TreeView.Resources>
Which gave me the below TreeView:
- Projectile A
- Projectile B
- Projectile C
- Particle A
- Particle B
- Particle C
However, because my data is actually a List
of OBJ
, there are child classes that are in that same list, I wanted to group the classes under its own Type
. i.e. new List<OBJ>() { new Projectiles(), new Particles() }
should have a node for Projectiles
, Particles
, etc. I created a Converter
that changes it into a Dictionary
, which then doesn't work with the above HierarchicalDataTemplate
because it is now a Dictionary<string, List<OBJ>
.
I then created a new HierarchicalDataTemplate
that handled the Dictionary<string, List<OBJ>
, see below.
<TreeView Name="MyTreeView" ItemsSource="{Binding OBJS,
Converter={StaticResource ItemsSourceConverter}}"
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Value}">
<TextBlock Text="{Binding Key}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
And the 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;
}
}
Which gave me the below TreeView, creating the proper groups:
- Projectiles
- Particles
But expanding them would give me the following two errors for each node inside Particles
or 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')
It seems that once you set TreeView.ItemTemplate
, it ignores all the DataTemplates
that you have defined in TreeView.Resources
?
In my first attempt, I was able to use DataType="{x:Type EntityType:Projectiles}"
to specify that I wanted the HierarchicalDataTemplate
to be used for Projectiles
objects, is there a DataType
syntax that will let me specify DataType="{x:Type Dictionary<string, List<OBJ>>}"
? So I can do something like the below?
<HierarchicalDataTemplate ItemsSource="{Binding Value}"
DataType="{x:Type Dictionary<string, List<OBJ>>}">
<TextBlock Text="{Binding Key}" />
</HierarchicalDataTemplate>
That way, in the end, I'll have the below:
- Projectiles
- Projectile A
- Projectile B
- Projectile C
- Particles
- Particle A
- Particle B
- Particle C
Edit: This should also work if I have sub-levels, see below.
- Projectiles
- Projectile SubType A
- Projectile A
- Projectile SubType B
- Projectile B
- Projectile C
- Projectile SubType A
- Particles
- Particle A
- Particle B
- Particle C