I have a TreeView
that looks like this:
<TreeView Grid.Row="1" x:Name="InspectionResultsTreeView"
ItemsSource="{Binding Source={StaticResource InspectionTypeGroupViewSource}, Path=Groups}"
ItemTemplate="{StaticResource InspectionTypeGroupsTemplate}">
</TreeView>
The ItemsSource
is a keyed resource that goes by the name of InspectionTypeGroupViewSource
:
<CollectionViewSource x:Key="InspectionTypeGroupViewSource" Source="{Binding Results}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Inspection.InspectionType" />
<PropertyGroupDescription PropertyName="Inspection" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
The role of this little thing is to take the ViewModel's Results
property:
private ObservableCollection<ICodeInspectionResult> _results;
public ObservableCollection<ICodeInspectionResult> Results
{
get { return _results; }
set { _results = value; OnPropertyChanged(); }
}
...and group it on two levels - first by InspectionType
, then by Inspection
- the result is a 3-level hierarchy with inspection types, inspections, and then individual inspection results. At this point a screenshot might help visualizing I guess:
So, the ItemTemplate
of the InspectionResultsTreeView
is another keyed resource, by the name of InspectionTypeGroupsTemplate
- that's the bold "inspection type" items:
<HierarchicalDataTemplate x:Key="InspectionTypeGroupsTemplate"
DataType="{x:Type CollectionViewGroup}"
ItemsSource="{Binding Items}"
ItemTemplate="{StaticResource InspectionGroupsTemplate}">
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center"
Text="{Binding Name}"
FontWeight="Bold"
TextWrapping="NoWrap"/>
<TextBlock Margin="4,0,4,0"
VerticalAlignment="Center"
Text="{Binding ItemCount, StringFormat=({0})}"
TextWrapping="NoWrap"/>
</StackPanel>
</HierarchicalDataTemplate>
And the ItemTemplate
of that template is an InspectionGroupsTemplate
- that's the individual inspections, with the "severity" icons:
<HierarchicalDataTemplate x:Key="InspectionGroupsTemplate"
DataType="{x:Type CollectionViewGroup}"
ItemsSource="{Binding Items}"
ItemTemplate="{StaticResource InspectionResultTemplate}">
<StackPanel Orientation="Horizontal">
<Image Style="{StaticResource IconStyle}"
Source="{Binding Name, Converter={StaticResource InspectionIconConverter}}"
VerticalAlignment="Center" />
<TextBlock Margin="4"
VerticalAlignment="Center"
Text="{Binding Name, Converter={StaticResource InspectionDescriptionConverter}}"
TextWrapping="NoWrap"/>
<TextBlock Margin="0,4,0,4"
VerticalAlignment="Center"
Text="{Binding ItemCount, StringFormat=({0})}"
TextWrapping="NoWrap"/>
</StackPanel>
</HierarchicalDataTemplate>
Lastly, the ItemTemplate
of this grouping is an InspectionResultTemplate
, which is for each individual inspection result:
<DataTemplate x:Key="InspectionResultTemplate"
DataType="{x:Type inspections:ICodeInspectionResult}">
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center"
Margin="4"
Text="{Binding Name}"
TextWrapping="NoWrap"/>
</StackPanel>
</DataTemplate>
The ICodeInspectionResult
interface has a string Name
property that I'm using here; this Name
is different from the Name
that's used in the grouping levels, where it's an object CollectionViewGroup.Name
- the underlying type of that Name
is that of the grouping, so level 1 is an InspectionType
, and level 2 is an Inspection
.
The problem is that I'm using more converters than I believe I'd need to, to convert this object Name
and access the members I need to access and display... but then, I need to display the number of items in each grouping so the DataType
ought to be a CollectionViewGroup
... right?
How can I do this without resorting to a converter for everything that needs to be displayed? How is this supposed to be done? Every TreeView
/ CollectionViewGroup
tutorial I could find was a trivial implementation.