SizeToContent not respecting SharedSizeGroups

83 views Asked by At

Using a window's SizeToContent="WidthAndHeight" property seems to break a grid's column and row definition's property SharedSizeGroup.

<Window x:Class="SizeTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow"
        SizeToContent="WidthAndHeight">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" SharedSizeGroup="MainColumnWidth" />
            <ColumnDefinition Width="*" SharedSizeGroup="MainColumnWidth" />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="*" SharedSizeGroup="MainRowHeight" />
            <RowDefinition Height="*" SharedSizeGroup="MainRowHeight" />
        </Grid.RowDefinitions>

        <Border BorderThickness="1" BorderBrush="Black" Grid.Column="0" Grid.Row="0" >
            <Button Width="100" Height="100" Margin="10" Content="A" />
        </Border>

        <Border BorderThickness="1" BorderBrush="Black" Grid.Column="1" Grid.Row="0" >
            <Button Width="100" Height="200" Margin="10" Content="B" />
        </Border>

        <Border BorderThickness="1" BorderBrush="Black" Grid.Column="0" Grid.Row="1" >
            <Button Width="200" Height="100" Margin="10" Content="C" />
        </Border>

        <Border BorderThickness="1" BorderBrush="Black" Grid.Column="1" Grid.Row="1" >
            <Button Width="100" Height="100" Margin="10" Content="D" />
        </Border>
    </Grid>
</Window>

For example, the code above produces the following:

Actual Output

However, I would expect it to produce similar to

Expected output

Where it sizes to the components but respects the shared group size.

Resizing instantly applies the shared group sizes but then you have to manually guess where the correct size is.

Is there any way to fix this?

If it makes any difference, I am using .NET 5.


Edit

Adding Grid.IsSharedSizeScope="True" to the window or the grid initially appears to solve the issue, but when resizing the window, the grid no longer fills the window.

Needs to resize grid

I suspect that what is happening is that without IsSharedSizeScope, the columns / rows are only the same size due to the Column / Row definition saying width / height is * but when IsSharedSizeScope is true, then the shared size scope come into effect, but for some reason stop the grid resizing when there is space for it to grow.

2

There are 2 answers

2
Lana On BEST ANSWER

Looks like you need to use UniformGrid

    <UniformGrid Rows="2" Columns="2">
        <Border BorderThickness="1" BorderBrush="Black">
            <Button Width="100" Height="100" Margin="10" Content="A" />
        </Border>

        <Border BorderThickness="1" BorderBrush="Black">
            <Button Width="100" Height="200" Margin="10" Content="B" />
        </Border>

        <Border BorderThickness="1" BorderBrush="Black">
            <Button Width="200" Height="100" Margin="10" Content="C" />
        </Border>

        <Border BorderThickness="1" BorderBrush="Black">
            <Button Width="100" Height="100" Margin="10" Content="D" />
        </Border>
    </UniformGrid>
0
thatguy On

Using a window's SizeToContent="WidthAndHeight" property seems to break a grid's column and row definition's property SharedSizeGroup.

No, in order to take advantage of shared size groups, you have to set a scope for the shared size groups to apply. That is what you do with the IsSharedSizeScope property attached property, which is false by default, which means initially there is no scope defined on any element, so the shared size groups will not apply.

<Grid IsSharedSizeScope="True">
   <Grid.ColumnDefinitions>
      <ColumnDefinition Width="*" SharedSizeGroup="MainColumnWidth" />
      <ColumnDefinition Width="*" SharedSizeGroup="MainColumnWidth" />
   </Grid.ColumnDefinitions>

   <Grid.RowDefinitions>
      <RowDefinition Height="*" SharedSizeGroup="MainRowHeight" />
      <RowDefinition Height="*" SharedSizeGroup="MainRowHeight" />
   </Grid.RowDefinitions>
   <!-- ...other grid definitions. -->
</Grid>

For example, the code above produces the following: [...] Resizing instantly applies the shared group sizes but then you have to manually guess where the correct size is.

This is not related to shared size groups, but to the Grid itself. You can remove all the shared size definitions and it will yield the same result. In fact, the shared size definitions are redundant, as giving each column and cell a * size, will scale them in the same proportion. See the documentation for reference.

Star sizing is used to distribute available space by weighted proportions.

Unfortunately, I cannot tell why the inital size fits the Grid content exactly instead of respecting the star sizes. However, applying a MinWidth and MinHeight solves the issue, if applicable.

<Grid IsSharedSizeScope="True">
   <Grid.ColumnDefinitions>
      <ColumnDefinition Width="*" MinWidth="200" />
      <ColumnDefinition Width="*" MinWidth="200" />
   </Grid.ColumnDefinitions>
   <Grid.RowDefinitions>
      <RowDefinition Height="*" MinHeight="200" />
      <RowDefinition Height="*" MinHeight="200" />
   </Grid.RowDefinitions>
   <!-- ...other grid definitions. -->
</Grid>

This could be the same or a similar issue with star-sizing like in this related question.

[...] when IsSharedSizeScope is true, then the shared size scope come into effect, but for some reason stop the grid resizing when there is space for it to grow.

This is expected, since setting a shared size group will treat sizes differently.

Columns and rows that participate in size-sharing do not respect Star sizing. In the size-sharing scenario, Star sizing is treated as Auto.

Consequently, if you apply a *, the Grid will be measured and the size will remain even after resizing.

As you question suggests, you are dealing with uniform cells in your grid. In this case, you can circumvent these issues by simply using the UniformGrid control, which is dedicated for this scenario.

Provides a way to arrange content in a grid where all the cells in the grid have the same size.

<UniformGrid>
   <Border BorderBrush="Black" BorderThickness="1">
      <Button Width="100" Height="100" Margin="10" Content="A" />
   </Border>
   <Border BorderBrush="Black" BorderThickness="1">
      <Button Width="100" Height="200" Margin="10" Content="B" />
   </Border>
   <Border BorderBrush="Black" BorderThickness="1">
      <Button Width="200" Height="100" Margin="10" Content="C" />
   </Border>
   <Border BorderBrush="Black" BorderThickness="1">
      <Button Width="100" Height="100" Margin="10" Content="D" />
   </Border>
</UniformGrid>