You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 02:27:03