问题
Following this question, I have another question about TreeView
.
What I already have is a TreeView
with HierarchicalDataTemplate
, in which I can change the HierarchicalDataTemplate
of level2 (like explained in the question and the answer).
What I want now, is to change the look of the expander of the Treeview
. For this, I have defined a ControlTemplate
named ctForTreeViewItem
, and I use it like this:
<Window.Resources>
<ControlTemplate x:Key="ctForTreeViewItem"
TargetType="{x:Type TreeViewItem}">
<Expander IsExpanded="True"
Background="Grey"
BorderBrush="Transparent"
Foreground="White"
BorderThickness="1,1,1,3">
<Expander.Header>
<Border BorderThickness="{TemplateBinding Border.BorderThickness}"
Padding="{TemplateBinding Control.Padding}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
Background="{TemplateBinding Panel.Background}"
Name="Bd"
SnapsToDevicePixels="True"
Grid.Column="1">
<ContentPresenter Content="{TemplateBinding HeaderedContentControl.Header}"
ContentTemplate="{TemplateBinding HeaderedContentControl.HeaderTemplate}"
ContentStringFormat="{TemplateBinding HeaderedItemsControl.HeaderStringFormat}"
ContentSource="Header"
Name="PART_Header"
HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</Border>
</Expander.Header>
<Expander.Content>
<ItemsPresenter x:Name="ItemsHost" />
</Expander.Content>
</Expander>
</ControlTemplate>
<DataTemplate x:Key="Level3Template">
<Border Background="LightBlue">
<TextBlock Text="Level3"/>
</Border>
</DataTemplate>
<HierarchicalDataTemplate x:Key="Level2RedTemplate"
ItemsSource="{Binding Value}"
ItemTemplate="{StaticResource Level3Template}">
<Border Background="Red">
<TextBlock Text="Level2"/>
</Border>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="Level2YellowTemplate"
ItemsSource="{Binding Value}"
ItemTemplate="{StaticResource Level3Template}">
<Border Background="Yellow">
<TextBlock Text="Level2"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="Level1Template"
ItemsSource="{Binding Value}"
ItemTemplateSelector="{StaticResource MySelector}">
<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="Template"
Value="{StaticResource ctForTreeViewItem}" />
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
<Border Background="Green">
<TextBlock Text="Level1"/>
</Border>
</HierarchicalDataTemplate>
</Window.Resources>
<TreeView Grid.Row="1"
Name="tv"
ItemsSource="{Binding Items}"
ItemTemplate="{StaticResource Level1Template}">
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="Template"
Value="{StaticResource ctForTreeViewItem}" />
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
This works for Level1 as expected, so on Level 1, I have TreeViewItems
with the defined ControlTemplate
and the Correct HierarchicalDataTemplate
.
However, it doesn't work on Level2, where I have an ItemTemplateSelector
. At this position, I get this error: System.Windows.Data Error: 25 : Both 'ItemTemplate' and 'ItemTemplateSelector' are set; 'ItemTemplateSelector' will be ignored.
Is there any way, that I can assign a
ControlTemplate
to theTreeViewItem
s, while keeping theItemTemplateSelector
? Or evenIs there any other way, that I can change the style of the expander of the
TreeView
?
回答1:
Your TreeViewItem ControlTemplate is broken. It ignores the data template selector because you explicitly override that by setting ContentTemplate on the ContentPresenter. That's similar to what's causing the (harmless) errors in your debug output stream as well: The level 2 templates inherit an ItemTemplateSelector
from their ancestors, in the same way that if you set ItemContainerStyle
once on the TreeView
, it will be inherited by all children of the treeview unless some intervening child overrides it explicitly. No need to set it more than once. Because the level 2 templates inherit ItemTemplateSelector
and override it with a different property, you get an error, but it's harmless.
I fixed the control template by changing the ContentPresenter for the Header to match the default TreeViewItem control template: I removed the Content
, ContentTemplate
, and ContentStringFormat
attributes. The ContentPresenter
has default behavior for all that stuff so you don't need to specify it explicitly.
<ContentPresenter
ContentSource="Header"
Name="PART_Header"
HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"
/>
The template/template selector errors are harmless but I was able to silence them by setting ItemTemplateSelector
explicitly to null on the level 2 hierarchical data templates:
<HierarchicalDataTemplate
x:Key="Level2RedTemplate"
ItemsSource="{Binding Value}"
ItemTemplateSelector="{x:Null}"
ItemTemplate="{StaticResource Level3Template}"
>
<Border Background="Red">
<TextBlock Text="Level2"/>
</Border>
</HierarchicalDataTemplate>
来源:https://stackoverflow.com/questions/47415104/both-itemtemplate-and-itemtemplateselector-are-set-itemtemplateselector-w