WPF中HeaderedItemsControl触发器修改模板无效的原因及解决办法
问题分析与解决
问题现象
编写了如下XAML代码:
<HeaderedItemsControl ItemsSource="{Binding ProjectInfo.ProgressEntries}" Focusable="False"> <HeaderedItemsControl.Style> <Style TargetType="HeaderedItemsControl"> <Style.Triggers> <Trigger Property="HasItems" Value="false"> <Setter Property="Template" > <Setter.Value> <ControlTemplate> // anything </ControlTemplate> </Setter.Value> </Setter> </Trigger> </Style.Triggers> </Style> </HeaderedItemsControl.Style> <HeaderedItemsControl.ItemTemplate> <DataTemplate> // items template </DataTemplate> </HeaderedItemsControl.ItemTemplate> <HeaderedItemsControl.Template> <ControlTemplate TargetType="HeaderedItemsControl"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <ContentPresenter ContentSource="Header" /> <Separator Grid.Row="1" /> <ItemsPresenter Grid.Row="2" /> </Grid> </ControlTemplate> </HeaderedItemsControl.Template> <HeaderedItemsControl.Header> <Grid Height="30"> // header </Grid> </HeaderedItemsControl.Header> </HeaderedItemsControl>
当数据源无条目时,HasItems=false的触发器无法修改Template,但改为设置Visibility=Collapsed时却能正常生效。
原因
WPF的属性值优先级规则:控件本地直接设置的属性值(比如代码里<HeaderedItemsControl.Template>的定义)优先级远高于样式触发器中的Setter值。所以即使触发器触发,也无法覆盖本地设置的Template。而Visibility没有在控件本地设置,所以触发器的Setter能正常生效。
解决方案
把默认的Template移到Style的<Setter>中,而非直接写在控件上,这样触发器的Setter就能覆盖这个默认值:
<HeaderedItemsControl ItemsSource="{Binding ProjectInfo.ProgressEntries}" Focusable="False"> <HeaderedItemsControl.Style> <Style TargetType="HeaderedItemsControl"> <!-- 将默认Template移到Style的Setter里 --> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="HeaderedItemsControl"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <ContentPresenter ContentSource="Header" /> <Separator Grid.Row="1" /> <ItemsPresenter Grid.Row="2" /> </Grid> </ControlTemplate> </Setter.Value> </Setter> <Style.Triggers> <Trigger Property="HasItems" Value="false"> <Setter Property="Template" > <Setter.Value> <ControlTemplate> // anything </ControlTemplate> </Setter.Value> </Setter> </Trigger> </Style.Triggers> </Style> </HeaderedItemsControl.Style> <HeaderedItemsControl.ItemTemplate> <DataTemplate> // items template </DataTemplate> </HeaderedItemsControl.ItemTemplate> <HeaderedItemsControl.Header> <Grid Height="30"> // header </Grid> </HeaderedItemsControl.Header> </HeaderedItemsControl>
这样当HasItems为false时,触发器的Template就能正常替换默认的Template了。
内容的提问来源于stack exchange,提问作者Barta
相关产品推荐
相关产品推荐

