Search code examples
c#.netwpfmvvmexpander

How to give Expander Full Width of Column in a Grid


I have an Expander and it should receive the full width of the column but I cant get it to work.

I tried to add the Horizontal(Content)Alignment = stretch on the TextBlock and on the Expander itself even on the Grid, but it is not working.

What I need is that the Expander takes about 90% of the width and the rest are assigned to the buttons as in the following example:

Example of Expander items taking up full width in a ListView.

I want to display e.g. a name and when you press on it, expands down and shows additional information and if the buttons are pressed, then the commands behind the buttons will be executed (no commands are binded in the example).

<ListView
    ItemsSource="{Binding log}"
    SelectionMode="Multiple"
    Style="{StaticResource ListViewStyle}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <Border BorderThickness="0,0,0,1" BorderBrush="Gray">
                <Grid HorizontalAlignment="Stretch">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="100*" />
                        <ColumnDefinition Width="5*" />
                        <ColumnDefinition Width="5*" />
                    </Grid.ColumnDefinitions>

                    <Expander Grid.Column="0"
                              HorizontalAlignment="Stretch"
                              IsExpanded="{Binding Mode=TwoWay, Path=IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}"
                              Style="{StaticResource ExpanderStyle}">
                        <Expander.Header>
                            <TextBlock Text="{Binding Name}" Foreground="White"
                                       HorizontalAlignment="Stretch" />
                        </Expander.Header>
                        <TextBlock
                            VerticalAlignment="Center"
                            FontSize="16"
                            Foreground="White"
                            Text="{Binding Description}" />
                    </Expander>

                    <Button Grid.Column="1"
                            Style="{StaticResource IconButton}">
                        <Button.Background>
                            <ImageBrush ImageSource="../icons/edit.png"
                                        Stretch="None" />
                        </Button.Background>
                    </Button>
                    <dialogButton:ConfirmButton Grid.Column="2"
                                                Question="{x:Static language:Strings.confirm}"
                                                Style="{DynamicResource IconButton}"
                                                Margin="0,0,10,0">
                        <dialogButton:ConfirmButton.Background>
                            <ImageBrush ImageSource="../icons/delete.png"
                                        Stretch="None" />
                        </dialogButton:ConfirmButton.Background>
                    </dialogButton:ConfirmButton>

                </Grid>
            </Border>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Styles

<Style x:Key="ExpanderDownHeaderStyle" TargetType="{x:Type ToggleButton}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ToggleButton}">
                <Border Padding="{TemplateBinding Padding}">
                    <Grid Background="Transparent" SnapsToDevicePixels="False">
                        <ContentPresenter HorizontalAlignment="Stretch" Margin="0" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Center"/>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="ExpanderStyle" TargetType="{x:Type Expander}">
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    <Setter Property="VerticalContentAlignment" Value="Stretch"/>
    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Expander}">
                <Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="3" SnapsToDevicePixels="true">
                    <DockPanel>
                        <ToggleButton x:Name="HeaderSite" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}" DockPanel.Dock="Top" FontStyle="{TemplateBinding FontStyle}" FontStretch="{TemplateBinding FontStretch}" FontWeight="{TemplateBinding FontWeight}" FocusVisualStyle="{StaticResource ExpanderHeaderFocusVisual}" FontFamily="{TemplateBinding FontFamily}" Foreground="{TemplateBinding Foreground}" FontSize="{TemplateBinding FontSize}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" MinHeight="0" MinWidth="0" Margin="1" Padding="{TemplateBinding Padding}" Style="{StaticResource ExpanderDownHeaderStyle}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        <ContentPresenter x:Name="ExpandSite" DockPanel.Dock="Bottom" Focusable="false" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Visibility="Collapsed"/>
                    </DockPanel>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsExpanded" Value="true">
                        <Setter Property="Visibility" TargetName="ExpandSite" Value="Visible"/>
                    </Trigger>

                    <Trigger Property="ExpandDirection" Value="Down">
                        <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Bottom"/>
                        <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Top"/>
                        <Setter Property="Background" Value="Transparent" />
                        <Setter Property="Style" TargetName="HeaderSite" Value="{StaticResource ExpanderDownHeaderStyle}"/>
                    </Trigger>

                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                    </Trigger>

                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

I also tried things from the following Threads

wpf - Header of Expander fit contents width?

Problem here is that the Buttons are pushed out of the view

Best Solution would be if the Expander just takes the width of the column so that I can adjust the widths of the element by the Grid.ColumnDefinition.


Solution

  • The issue is that the item container, a ListViewItem does not stretch its content by default. You have to create an item container style in order to set the HorizontalContentAlignment to Stretch.

    <ListView.ItemContainerStyle>
       <Style TargetType="{x:Type ListViewItem}">
          <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
       </Style>
    </ListView.ItemContainerStyle>