Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Stretch ListBox Height 100% of Grid.Row?

I'm attempting to stretch the height of a ListBox 100% of the height of the parent grid (i.e. 90% of the height of the parent view); even if the listboxes are empty. I should note that VerticalAlignment="Stretch" doesn't seem to work, so I've removed it from the ListBox and StackPanel elements. As of now, the ListBox only stretches as far as it needs to in order to accommodate the number of items it contains. I understand that the row definitions should work but if both lists are empty, they both shrink to a few pixels tall (along with the grid rows). Could something cause these rows to shrink despite the explicit height declaration?

<Grid.ColumnDefinitions>
        <ColumnDefinition Width=".24*"/>
        <ColumnDefinition Width=".73*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height=".9*"/>
        <RowDefinition Height=".1*"/>
    </Grid.RowDefinitions>
    <ListBox Grid.Column="0" Grid.Row="0" Name="Subdivisions" SelectedItem="{Binding SelectedSubdivisionViewModel}" ItemsSource="{Binding Path=Subdivisions}" Grid.IsSharedSizeScope="True">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <Border BorderBrush="#FF4788c8" BorderThickness="1,1,1,1" CornerRadius="8,8,8,8">
                        <Expander IsExpanded="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}">
                            <Expander.Header>
                                <StackPanel>
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="*" SharedSizeGroup="col1" />
                                            <ColumnDefinition Width=".1*" SharedSizeGroup="col2" />
                                            <ColumnDefinition Width="*" SharedSizeGroup="col3" />
                                        </Grid.ColumnDefinitions>
                                        <Grid.RowDefinitions>
                                            <RowDefinition/>
                                            <RowDefinition/>
                                        </Grid.RowDefinitions>
                                        <TextBlock Grid.Column="0" Grid.Row="0">
                                            <TextBlock.Text>
                                                <MultiBinding StringFormat="Name: {0}">
                                                  <Binding Path="SubdivisionName" />
                                                  <Binding Path="SubdivisionID" />
                                                </MultiBinding>
                                            </TextBlock.Text>
                                        </TextBlock>
                                        <TextBlock Grid.Column="2" Grid.Row="0">
                                            <TextBlock.Text>
                                                <MultiBinding StringFormat="ID: {0}">
                                                  <Binding Path="SubdivisionName" />
                                                  <Binding Path="SubdivisionID" />
                                                </MultiBinding>
                                            </TextBlock.Text>
                                        </TextBlock>
                                        <TextBlock Grid.Column="2" Grid.Row="1">
                                            <TextBlock.Text>
                                                <MultiBinding StringFormat="ID: {0}">
                                                  <Binding Path="SubdivisionName" />
                                                  <Binding Path="SubdivisionID" />
                                                </MultiBinding>
                                            </TextBlock.Text>
                                        </TextBlock>
                                    </Grid>
                                </StackPanel>
                            </Expander.Header>
                            <StackPanel>
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="*"/>
                                        <ColumnDefinition/>
                                        <ColumnDefinition/>
                                    </Grid.ColumnDefinitions>
                                    <Grid.RowDefinitions>
                                        <RowDefinition />
                                        <RowDefinition />
                                    </Grid.RowDefinitions>
                                    <TextBlock Text="{Binding ElementName=SubdivisionID}" />
                                    <TextBlock Text="{Binding Path=SubdivisionID}" />
                                </Grid>
                            </StackPanel>
                        </Expander>
                    </Border>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
like image 243
alan Avatar asked Mar 20 '11 04:03

alan


3 Answers

The stackpanels make it compress. Remove it and it'll fill the full height

like image 148
Tjeerd Mulder Avatar answered Nov 08 '22 15:11

Tjeerd Mulder


I was able to achieve the desired height by binding the ListBox height property to the ActualHeight of the LayoutRoot Grid via the XAML below:

<Grid x:Name="LayoutRoot" Background="LightGray">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width=".24*"/>
        <ColumnDefinition Width=".73*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height=".9*"/>
        <RowDefinition Height=".1*"/>
    </Grid.RowDefinitions>
    <ListBox Name="Subdivisions" SelectedItem="{Binding SelectedSubdivisionViewModel}" ItemsSource="{Binding Path=Subdivisions}" Grid.IsSharedSizeScope="True" Height="{Binding ElementName=LayoutRoot, Path=ActualHeight}" >

The important bit being:

Height="{Binding ElementName=LayoutRoot, Path=ActualHeight}"

Also achievable via ancestor type:

Height="{Binding Path=ActualHeight, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}}"
like image 41
alan Avatar answered Nov 08 '22 15:11

alan


The code you've posted does exactly what the parent grid's row height definition has declared: take up 90% of the available height.

*.1 = 10% of height
*.9 = 90% of the height

Often times its useful to remove the clutter from the xaml and start with something simple to help with the layout. Here's a sample with your code's Grid column/row definition's, but with less clutter and some background color to show the entire ListBox.

  • The first ListBox has several items, while the 2nd ListBox only has a few items.
  • Both ListBoxes are in the first row and fill 90% of the available space.
  • The 2nd Row contains a grid that fills the rest of the space; you can see that it takes up 10% of the available space.

Note that the first ListBox doesn't declare a Column or Row index; when no index is used, it is assumed to be 0, i.e., Grid.Row="0" Grid.Column=0.

<Grid Background="Red">

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width=".24*"/>
        <ColumnDefinition Width=".73*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height=".9*"/>
        <RowDefinition Height=".1*"/>
    </Grid.RowDefinitions>

    <ListBox Background="LightGray"
             ItemsSource="{x:Static Fonts.SystemFontFamilies}"/>

    <ListBox Grid.Column="1" Grid.Row="0" Background="LightSlateGray">
        <ListBoxItem>John</ListBoxItem>
        <ListBoxItem>Jane</ListBoxItem>
        <ListBoxItem>Fido</ListBoxItem>
    </ListBox>

    <Grid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Background="Tomato" />

</Grid>
like image 2
Metro Smurf Avatar answered Nov 08 '22 14:11

Metro Smurf