7

Getting three columns have the same width is done by setting Width to Auto.

<Grid x:Name="myGrid">
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>

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

  <Label Grid.Row="0" Grid.Column="0">One</Label>
  <Label Grid.Row="0" Grid.Column="1" x:Name="label1">Two</Label>
  <Label Grid.Row="0" Grid.Column="2">Three</Label>
</Grid>

I want to achieve that if middle column is collapsed or hidden that the other two take up remaining space and get equal width.

If I just set Visibility to Collapsed or Hidden because of the Width="*", the other two columns width stays the same.

<Label Grid.Row="0" Grid.Column="1" Visibility="Collapsed">Two</Label>

enter image description here

I achieved desired functionality by programatically setting second column width to auto, but am looking for some other solution (preferably xaml way one).

private void Button_Click(object sender, RoutedEventArgs e)
{
  this.myGrid.ColumnDefinitions[1].Width = GridLength.Auto;
  this.label1.Visibility = Visibility.Collapsed;
}
Andrea Antonangeli
  • 1,242
  • 1
  • 21
  • 32
broadband
  • 3,266
  • 6
  • 43
  • 73
  • 1
    The only XAML way of doing it I can think of is Binding. – Robert Nov 15 '18 at 09:35
  • You can either size relative to self (star sizing / fixed size) or relative to content size (auto), you can't do both (star sizing but if 0 width content switch to auto), you'll have to code a solution manually or create your own grid-like control that supports that. – Ronan Thibaudau Nov 15 '18 at 09:46
  • 1
    See [WPF Grid Column and Row Hiding](https://www.codeproject.com/Articles/437237/WPF-Grid-Column-and-Row-Hiding) on Code Project. They show a way to hide a column by just using a binding. – ManDani Nov 15 '18 at 11:08

3 Answers3

9

The desired behaviour can be achieved using a UniformGrid.

Make sure to set the number of rows to 1.

<UniformGrid Rows="1">
    <Label>One</Label>
    <Label>Two</Label>
    <Label>Three</Label>
</UniformGrid>

3 cols

The remaining elements are evenly spaced.

<UniformGrid Rows="1">
    <Label>One</Label>
    <Label Visibility="Collapsed">Two</Label>
    <Label>Three</Label>
</UniformGrid>

2 cols

tpol
  • 910
  • 10
  • 16
2

I added Xaml Binding as suggested by Rob like this:

<Grid.ColumnDefinitions>
  <ColumnDefinition Width="*" />
  <ColumnDefinition Width="{Binding MiddleColumnWidth}" />
  <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

<Label Grid.Row="0" Grid.Column="0">One</Label>
<Label Grid.Row="0" Grid.Column="1" Visibility="{Binding IsSecondLabelVisible}">Two</Label>
<Label Grid.Row="0" Grid.Column="2">Three</Label>

Code behind xaml:

private bool ShowOnlyTwoColumns;

private GridLength MiddleColumnWidth
{
  get
  {
    if (ShowOnlyTwoColumns)
      return GridLength.Auto; // Auto collapses the grid column when label is collapsed

    return new GridLength(1, GridUnitType.Star);
  }
}

private Visibility IsSecondLabelVisible
{
  get { return this.ShowOnlyTwoColumns ? Visibility.Collapsed : Visibility.Visible; }
}
broadband
  • 3,266
  • 6
  • 43
  • 73
0

I'm late, but I want to present my solution, in case it is useful to anyone.

I use this converter

public class BooleanToAutoOrStarGridLengthConverter : MarkupExtension, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is bool isStar)
            return new GridLength(1, isStar ? GridUnitType.Star : GridUnitType.Auto);
        return new GridLength(0, GridUnitType.Star);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is GridLength gridLength && gridLength.GridUnitType == GridUnitType.Star)
            return true;
        return false;
    }

    public override object ProvideValue(IServiceProvider serviceProvider) => this;
} 

in XAML like this:

<Grid.ColumnDefinitions>
  <ColumnDefinition Width="*" />
  <ColumnDefinition Width="{Binding IsSecondLabelVisible, Converter={BooleanToAutoOrStarGridLengthConverter}}" />
  <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

<Label Grid.Row="0" Grid.Column="0">One</Label>
<Label Grid.Row="0" Grid.Column="1" Visibility="{Binding IsSecondLabelVisible}">Two</Label>
<Label Grid.Row="0" Grid.Column="2">Three</Label>
h.m.i.13
  • 353
  • 1
  • 6
  • 17