wpfxamltriggers

WPF HeaderedItemsControl changing template in trigger not working


I have this xaml code:

<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>

The source does not have any items in it, but the trigger doesn't change the template. But when I change the trigger to a simple visibility:

<Style.Triggers>
    <Trigger Property="HasItems" Value="false">
        <Setter Property="Visibility" Value="Collapsed" />
    </Trigger>
</Style.Triggers>

It does what it should do. Why is that happening, and how can I fix this?


Solution

  • This is because setter from style cannot override template that was set directly on the element. In order to fix the issue you need to move template declaration to style setters.

    Here's my working example for Button

    <Button>
        <Button.Style>
            <Style TargetType="Button">
                <Style.Setters>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="Button">
                                <Grid>
                                    <Ellipse Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" />
                                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                                </Grid>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style.Setters>
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="Button">
                                    <Grid>
                                        <Ellipse Fill="Red" />
                                        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                                    </Grid>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
        Hello
    </Button>