Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Grid sizing

This question is hard to describe succinctly, so bear with me.

Currently I have a Grid with two rows. The first row's height is Auto, and the second row's height is *, so when I resize the window, the second row grows and shrinks according to the window.

This is the basic layout:

<Window>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Border>
            ...
        </Border>
        <Border Grid.Row="2">
            ...
        </Border>
    </Grid>
</Window>

Here is a poor sketch of the existing behaviour:

____    ____    ____
     ->      ->
____    ____    ____
                ____
        ____
____

I would like to add a sort of 'minimum height' to the second row, so that when I resize the window small enough, the second row stops shrinking, and the first row starts shrinking instead.

Desired behaviour:

____    ____    ____
     ->      -> ____
____    ____
                ____
        ____
____

Is there a simple way to get the minimum height for the second row, and force the first one to shrink?

More details:

When I set MinHeight on the second row, it just clips the grid when I resize it below that size.

The size of the controls in the first row are unknown at compile time, but known at runtime. If it is a necessary part of the solution, I could set the row's MaxHeight, but right now an Auto height is working.

The controls in the second row do not have an explicit size. They are allowed to be resized, but I'm trying to keep them from becoming smaller than the desired minimum height.

like image 992
Kendall Frey Avatar asked Jun 21 '12 18:06

Kendall Frey


People also ask

How do I resize a grid in WPF?

If your Grid has more than one row, set the RowSpan attached property to the number of rows. Then set the HorizontalAlignment property to Left or Right (which alignment you set depends on which two columns you want to resize). Finally, set the VerticalAlignment property to Stretch.

What is GridView WPF?

The GridView view mode displays a list of data items by binding data fields to columns and by displaying a column header to identify the field. The default GridView style implements buttons as column headers.

What is the star in WPF?

You can use star sizing when setting the height of rows or width of columns in a Grid to distribute space in a Grid across multiple rows or columns. You can use integer values preceding each '*' (star) to indicate the relative size of rows or columns.

What is Grid in XAML?

In XAML a Grid is made up of a series of rows and columns. By specifying the row and column of an element within a Grid, you can place and space other elements within a user interface. Rows and columns are defined with the RowDefinition and ColumnDefinition elements.


1 Answers

The size of the controls in the first row are unknown at compile time, but known at runtime. If it is a necessary part of the solution, I could set the row's MaxHeight, but right now an Auto height is working.

I think this is probably going to be the easiest solution. Bind the MaxHeight to the calculated value at runtime:

<Grid.RowDefinitions>
    <RowDefinition Height="*" MaxHeight="{Binding MyProperty}"/>
    <RowDefinition Height="*" MinHeight="100"/>
</Grid.RowDefinitions>

Edit: The previous solution is close, but not correct. Here is a way to achieve your desired result, however, not sure if it's the optimal approach:

<Grid ShowGridLines="True" Name="myGrid">
    <Grid.Resources>
        <local:RowHeightConverter x:Key="rowHeightConverter" />
    </Grid.Resources>
    <Grid.RowDefinitions>
        <RowDefinition Name="row1" MaxHeight="{Binding MyProperty}">
            <RowDefinition.Height>
                <MultiBinding Converter="{StaticResource rowHeightConverter}">
                    <Binding Path="ActualHeight" ElementName="row2" />
                    <Binding Path="ActualHeight" ElementName="myGrid" />
                    <Binding Path="MaxHeight" ElementName="row1" />
                </MultiBinding>
            </RowDefinition.Height>
        </RowDefinition>
        <RowDefinition Name="row2" Height="*" MinHeight="300"/>
    </Grid.RowDefinitions>
</Grid>

And your converter:

public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    double row2Height = (double)values[0];
    double gridHeight = (double)values[1];
    double row1MaxHeight = (double)values[2];

    if (gridHeight - row2Height >= row1MaxHeight)
    {
        return gridHeight - row2Height;
    }

    return row1MaxHeight;
}
like image 192
Dylan Meador Avatar answered Oct 13 '22 12:10

Dylan Meador