How can I tell a grid which column to shrink when needed

186 Views Asked by At

I'm wanting to limit a Grid.ColumnDefinition to a maximum width but I do not know the width to do this programatically. Consider the following XAML:

   <Grid MaxWidth="150" HorizontalAlignment="Left">
      <Grid.ColumnDefinitions>
         <ColumnDefinition Width="Auto" />
         <ColumnDefinition Width="Auto" />
      </Grid.ColumnDefinitions>
      
      <Grid.RowDefinitions>
         <RowDefinition Height="Auto" />
      </Grid.RowDefinitions>

      <TextBlock Grid.Column="0" Text="A" TextWrapping="Wrap" Background="LightGreen"  />
      <TextBlock Grid.Column="1" Text="B" TextWrapping="NoWrap" Background="LightSteelBlue" />      
   </Grid>

The Grid is 150px wide at most but can be less. The TextBlock in column 0 is Wrap. The TextBlock in column 1 is NoWrap. Background colors added simply for clarity. Result:

enter image description here

Now let's change the text:

      <TextBlock Grid.Column="0" Text="I'm long but I wrap" TextWrapping="Wrap" Background="LightGreen"  />
      <TextBlock Grid.Column="1" Text="I'm a long single line" TextWrapping="NoWrap" Background="LightSteelBlue" />      

Result:

enter image description here

The wrappable text does not wrap. Seems no feedback is provided from the Grid to the TextBlock. The behavior I want is for the Grid to realize that its columns being Auto have expanded past its own MaxWidth property and attempt to shrink the contents in the columns. The TextBlock that is NoWrap won't abide by this request while the TextBlock with Wrap would. Hence the output would be:

enter image description here

I can't figure out a way to do this with any * sizing since I don't want the grid to take this much space unless the contents are needed. Incidentally the actual Grid has many columns of many potential sizes. This is a shortened example.

[Edit]: My solution is a hack and I don't care for it, but it works. I created a property on my model which determines the content that can appear in other columns including images, margins, text, etc. Then it subtracts from the grid size to find a maximum width for a TextBlock which has Wrap set. Works just fine but is ugly as can be.

1

There are 1 best solutions below

2
On

Although Auto does not work well for you, doing the * can work wonders. Instead of just a blind-eye to * for all other columns, you can do [a numeric value]*, like Width="120*" which will allocate the 120, but, if there is more room, it will get the rest.

Now, that said, if you have SOME columns that you know would be fixed, like some date field which is always 100 width, or some string type category of 1 character, maybe a fixed width of 10, but the rest are otherwise flexible. Just blend them something like

Width 100
Width 10
Width 500*
Width 250*

So, if your screen has available width of 1200, columns 1 and 2 will remain at their fixed widths. However, the 500* and 250* will get their baseline width and then equally split the remaining width between them. The more "*"-based columns to split the widths, they all split the available space.

Have you tried doing something like that?