WPF: Separate Grids, Auto-Sized Columns/Rows With Synchronized Dimensions

,

The design specification calls for two Grids. One column in each is to auto-size its width to its content. “No problem—<ColumnDefinition Width=”Auto” /> will take care of that,” you think. Then you notice a footnote: “The widths both auto-sized columns should match. Both columns should be the width of the wider column’s content.

How do you implement this? Setting the widths to the same explicit value (e.g. Width=150″) will result in the two columns having the same width but that width won’t necessarily match the content. Using a proportionate value (e.g. Width=*) won’t auto-size the columns to their content. Width=Auto” auto-sizes but doesn’t link column widths. None of these are acceptable. How do you make this happen?

SharedSizeGroup

WPF has just the functionality you need. A SharedSizeGroup allows sizing properties to be shared between ColumnDefinitions and/or RowDefinitions—even across grids. Let’s take a look!

Consider these two grids. Both center columns have a width of “auto” and so automatically adjust to the width of their contained content. No surprises here.

In XAML, both grids’ Grid.ColumnDefinitions are identical:

<Grid.ColumnDefinitions>
    <ColumnDefinition />
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition />
</Grid.ColumnDefinitions>

How do we link the center columns’ widths? Simply assign the appropriate column definitions to the same SharedSizeGroup. Then, set Grid.IsSharedSizeScope to true on an element that is a parent of both grids.

Make the appropriate change to each grid’s Grid.ColumnDefinition:

<Grid.ColumnDefinitions>
    <ColumnDefinition />
    <ColumnDefinition SharedSizeGroup="centerColumn" Width="Auto" />
    <ColumnDefinition />
</Grid.ColumnDefinitions>

Both grids are contained within the same StackPanel so set Grid.IsSharedSizeScope on that element:

<StackPanel Grid.IsSharedSizeScope="True" HorizontalAlignment="Stretch" Margin="10">

The result? Both center columns are now auto-sized to the width of whichever one contains the widest content—exactly what the design specification called for!

Discussion

Our example focused on linking two columns’ widths. It’s just as easy to synchronize column heights. Simply assign their RowDefinitions to the same SharedStyleGroup.

<!-- in grid 1 -->
<Grid.RowDefinitions>
    <RowDefinition Height="Auto" SharedSizeGroup="rowGroup1" />
    <RowDefinition />
</Grid.RowDefinitions>

<!-- in grid 2 -->
<Grid.RowDefinitions>
    <RowDefinition Height="Auto" SharedSizeGroup="rowGroup1" />
    <RowDefinition />
</Grid.RowDefinitions>

SharedStyleGroups can be used to link column/row dimensions within the same grid. In this example, the grid’s top and bottom row’s heights are linked. Notice that Grid.IsSharedScope is set on the Grid instead of on the StackPanel (as in our main example). This is appropriate as the SharedSizeGroup is only used within this grid.

<Grid Grid.IsSharedSizeScope="True">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" SharedSizeGroup="rowGroup" />
        <RowDefinition />
        <RowDefinition Height="Auto" SharedSizeGroup="rowGroup" />
    </Grid.RowDefinitions>
    <!-- grid content goes here -->
</Grid>

If you assign a RowDefinition and a ColumnDefinition to the same style group, the row will be as tall as the column is wide if the column is wider than the row’s height; otherwise, the column will be as wide as the row is tall.

<Grid.ColumnDefinitions>
    <ColumnDefinition SharedSizeGroup="group1" Width="Auto" />
    <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition SharedSizeGroup="group1" Height="Auto" />
</Grid.RowDefinitions>

SharedSizeGroup names may contain letters, numbers and underscores. They may not start with numbers and must not be empty.

Example Code

Here’s the complete XAML for our main example:

<Window x:Class="SharedSizeExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="SharedSizeGroup Article Example 2" Width="500" Height="150">
    <StackPanel Grid.IsSharedSizeScope="True" HorizontalAlignment="Stretch" Margin="10">
        <TextBlock>Grid 1:</TextBlock>
        <Border BorderBrush="Black" BorderThickness="1">
            <Grid ShowGridLines="True">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition SharedSizeGroup="centerColumn" Width="Auto" />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Column="0">Column 0</TextBlock>
                <TextBlock Grid.Column="1">Column 1 - Lots of Text Makes This Column Wide</TextBlock>
                <TextBlock Grid.Column="2">Column 2</TextBlock>
            </Grid>
        </Border>

        <TextBlock Margin="0 10 0 0">Grid 2:</TextBlock>
        <Border BorderBrush="Black" BorderThickness="1">
            <Grid ShowGridLines="True">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition SharedSizeGroup="centerColumn" Width="Auto" />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Column="0">Column 0</TextBlock>
                <TextBlock Grid.Column="1">Column 1</TextBlock>
                <TextBlock Grid.Column="2">Column 2</TextBlock>
            </Grid>
        </Border>
    </StackPanel>
</Window>

4 thoughts on “WPF: Separate Grids, Auto-Sized Columns/Rows With Synchronized Dimensions

  1. Nicole

    Can this also be done with Grids in separate controls? I have three user controls that each have a grid with two columns. I am showing all three user controls in grid. Can column 0 width of all three user controls be tied together?

    Reply
    1. Ben Gribaudo Post author

      It sure can! If you take each Grid from the example, place it in a UserControl then insert that UserControl where the Grid used to be, the columns will still participate in the SharedSizeGroup.

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *