Search code examples
c#wpfxamlcontroltemplateexpander

Styled Expander Control Template and not able to view Expanded Content on Click


I am just styling the Expander Control in WPF. I have defined only the styles in Expander Control Template, but I am not able to view the content of expander when I click on it. I guess I have to define the expander trigers also ? but I don't know which triger and how to define it. Also why I have to define triggers when I am just styling the expander.

<Window x:Class="ExpanderControl.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Style TargetType="Expander">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Expander}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="30"></RowDefinition>
                                <RowDefinition Height="0" Name="contentRow"></RowDefinition>
                            </Grid.RowDefinitions>
                            <!--Expander Header-->
                            <Border Background="AliceBlue"
                                    Grid.Row="0"
                                    >
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="*"></ColumnDefinition>
                                        <ColumnDefinition Width="20"></ColumnDefinition>
                                    </Grid.ColumnDefinitions>
                                    <ContentPresenter Grid.Column="0" ContentSource="Header"
                                                      RecognizesAccessKey="True"
                                                      VerticalAlignment="Center"
                                                      HorizontalAlignment="Left"
                                                      Margin="5"
                                                      ></ContentPresenter>
                                    <ToggleButton Grid.Column="1">
                                        <TextBlock>x</TextBlock>
                                    </ToggleButton>
                                </Grid>
                            </Border>

                            <!--Expander Content-->
                            <Border Background="Aqua" Grid.Row="1">
                                <ContentPresenter  Grid.Row="1"></ContentPresenter>
                            </Border>
                        </Grid>


                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <Expander Header="Expander" HorizontalAlignment="Left" Margin="205,95,0,0" VerticalAlignment="Top" Width="200">
            <Grid Background="#FFE5E5E5">
                <Menu>
                    <MenuItem Header="hi"></MenuItem>
                </Menu>

            </Grid>
        </Expander>

    </Grid>
</Window>

Solution

  • At the moment there is no action linked to ToggleButton. You need to utilize Expander.IsExpanded property by binding it

    1. To ToggleButton.IsChecked
    2. To Border.Visibility via BooleanToVisibilityConverter (custom or built in)
    3. Set content row height to Auto

    This way changing ToggleButton.IsChecked will change Expander.IsExpanded which in turn will affect visibility of content Border. It will also work when you change IsExpanded property from outside.

    This is working XAML

    <Window.Resources>
       <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
       <Style TargetType="{x:Type Expander}">
          <Setter Property="Template">
             <Setter.Value>
                <ControlTemplate TargetType="{x:Type Expander}">
                   <Grid>
                      <Grid.RowDefinitions>
                         <RowDefinition Height="30"/>
                         <RowDefinition Height="Auto" Name="contentRow"/>
                      </Grid.RowDefinitions>
                      <!--Expander Header-->
                      <Border Background="AliceBlue" Grid.Row="0">
                         <Grid>
                            <Grid.ColumnDefinitions>
                               <ColumnDefinition Width="*"/>
                               <ColumnDefinition Width="20"/>
                            </Grid.ColumnDefinitions>
                            <ContentPresenter Grid.Column="0" ContentSource="Header" RecognizesAccessKey="True" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="5" />
                            <ToggleButton Grid.Column="1" Content="x" IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsExpanded}"/>
                         </Grid>
                      </Border>
                      <!--Expander Content-->
                      <Border Background="Aqua" Grid.Row="1" Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsExpanded, Converter={StaticResource BooleanToVisibilityConverter}}">
                         <ContentPresenter/>
                      </Border>
                   </Grid>
                </ControlTemplate>
             </Setter.Value>
          </Setter>
       </Style>
    </Window.Resources>
    

    EDIT

    If you want whole header to be able to expand/collapse your Expander you need to bring ContentPresenter for Header into Content of ToggleButton. In your case basically bring header Grid into ToggleButton.Content

    <!--Expander Header-->
    <ToggleButton IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsExpanded}" HorizontalContentAlignment="Stretch" Grid.Row="0">
       <Grid>
          <Grid.ColumnDefinitions>
             <ColumnDefinition Width="*"/>
             <ColumnDefinition Width="20"/>
          </Grid.ColumnDefinitions>
          <ContentPresenter Grid.Column="0" ContentSource="Header" RecognizesAccessKey="True" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="5" />
          <TextBlock Grid.Column="1" Text="x" HorizontalAlignment="Center" VerticalAlignment="Center" />
       </Grid>
    </ToggleButton>