How to style a WPF Expander Header?
Asked Answered
L

3

59

I would like to apply a style on a WPF Expander Header. In the following XAML I have an Expander but the style is for all of it not just for the header.

Thanks.

<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="640"
>
    <StackPanel>
        <StackPanel.Resources>
            <Style TargetType="Expander">
                <Style.Resources>
                    <LinearGradientBrush x:Key="BackBrush" StartPoint="0.5,0" EndPoint="0.5,1">
                        <GradientStop Color="#EF3132" Offset="0.1" />
                        <GradientStop Color="#D62B2B" Offset="0.9" />
                    </LinearGradientBrush>
                </Style.Resources>
                <Setter Property="Background" Value="{StaticResource BackBrush}"/>
            </Style>
        </StackPanel.Resources>
        <Expander>
            <StackPanel>
                <TextBlock>Bike</TextBlock>
                <TextBlock>Car</TextBlock>
                <TextBlock>Truck</TextBlock>
            </StackPanel>
        </Expander>
    </StackPanel>
</Page>
Lacerate answered 19/3, 2009 at 9:9 Comment(0)
L
63

I have combined some XAML from Josh Smith and MSDN and came up with a solution. Indeed, the control (al least the header) must be retemplated.

<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400">
    <StackPanel>
        <StackPanel.Resources>

            <Style TargetType="Border" x:Key="RacePitBorderStyle" >
                <Style.Resources>
                    <LinearGradientBrush x:Key="BackBrush" StartPoint="0.5,0" EndPoint="0.5,1">
                        <GradientStop Color="#EF3132" Offset="0.1" />
                        <GradientStop Color="#D62B2B" Offset="0.9" />
                    </LinearGradientBrush>
                </Style.Resources>
                <Setter Property="Background" Value="{StaticResource BackBrush}"/>
            </Style>

            <DataTemplate x:Key="titleText">
                <Border Style="{StaticResource RacePitBorderStyle}" Height="24">
                    <TextBlock Text="{Binding}" 
                        Margin="4 0"
                        VerticalAlignment="Center"
                        Foreground="White"
                        FontSize="11" 
                        FontWeight="Normal"
                        Width="{Binding
                        RelativeSource={RelativeSource
                        Mode=FindAncestor,
                        AncestorType={x:Type Expander}},
                        Path=ActualWidth}"
                        TextWrapping="Wrap"/>
                </Border>
            </DataTemplate>

            <Style TargetType="{x:Type Expander}">
                <Setter Property="HeaderTemplate" Value="{StaticResource titleText}"/>
            </Style>

        </StackPanel.Resources>

        <Expander Name="hcontCtrl" Header="This is the header.">
            <StackPanel>
                <TextBox>This is a textbox</TextBox>
                <Button>A button</Button>
            </StackPanel>
        </Expander>

    </StackPanel>
</Page>
Lacerate answered 19/3, 2009 at 11:6 Comment(4)
I found getting the expander width a real problem, and you code does this. It works in xamlpad flawlessly. However in my code it does not and causes terrible graphical lag. Width="{Binding RelativeSource{RelativeSource Mode=FindAncestor,AncestorType={x:Type Expander}}, Path=ActualWidth}"> By adding the above it works, but lags. if I remove it, or change Path=Width, it doesn't work and the lag goes away.Toilworn
Just what I needed. Thanks! Sometimes digging deep into XAML is a headache.Jonellejones
I'd suggest to remove the style and use 'HeaderTemplate' property directly on the expander. This allows to keep your default style on it.Alton
This style looks fine on a datagrid grouping header, but it takes a lot of resources. After using this style, I get a 1 second lag after clicking on a datagrid row and the moment when it is selected. Without this style, everything works quick. I only have 300 rows in my datagrid.Botel
U
26

I think Vasile's answer is on the right track, but it seems like it does a lot more than the original poster needed. All the original question was asking to do was to change the background of the header. While the change presented does do that, it also does other things.

One of these other things is to replace the default implementation, I believe a ContentPresenter, with a TextBlock. So what happens when later we change our Expander so that the header is more complicated? Maybe something like:

<Expander>
    <Expander.Header>
        <StackPanel>
            <Border height="5" width="5" Foreground="Blue"/>
            <TextBlock>Ha!</TextBlock>
        </StackPanel>
    </Expander.Header>
</Expander>

I don't know, but it's not good. Instead, I think we want to keep this simple.

<DataTemplate x:Key="expanderHeader">
    <ContentPresenter
        Content={Binding}
        TextBlock.Background={StaticResource myBrush}/>
</DataTemplate>

<Style TargetType="Expander">
    <Setter Property="HeaderTemplate" Value="{StaticResource expanderHeader}"/>
</Style>

That way when someone puts something that is not just text in our styled expander, we don't break. If you want to make sure you wrap the entirety of what they do with this background, which is probably desired, that would look like:

<DataTemplate x:Key="expanderHeader">
    <Border Background={StaticResource myBrush}>
        <ContentPresenter Content={Binding}/>
    </Border>
</DataTemplate>
Uprising answered 16/5, 2014 at 14:9 Comment(0)
D
7

Depends what you want to style -- you can style any part of it. If you want to change the content in the header, just place all your UI in the Expander.Header property, and it'll show in the header area.

if that does't meet your needs, you probably need to re-template the control. Take a look at the control templates shipped in WPF here

Dolli answered 19/3, 2009 at 9:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.