Hide grid row in WPF

WpfGrid

Wpf Problem Overview


I have a simple WPF form with a Grid declared on the form. This Grid has a bunch of rows:

<Grid.RowDefinitions>
    <RowDefinition Height="Auto" MinHeight="30" />
    <RowDefinition Height="Auto" Name="rowToHide" />
    <RowDefinition Height="Auto" MinHeight="30" />
</Grid.RowDefinitions>

The row named rowToHide contains a few input fields and I want to hide this row after I detect I don't need these fields. It's simple enough to just set Visibility = Hidden to all items in the row, but the row still takes up space in the Grid. I tried setting Height = 0 to the items, but that didn't seem to work.

You can think of it like this: You have a form, in there you have a drop down saying "Payment Type", and if the person selects "Cash", you want to hide the row containing the Card details. It isn't an option to start the form with this hidden already.

Wpf Solutions


Solution 1 - Wpf

Row does not have a Visibility property, so as others have said, you need to set the Height. Another option is to use a converter, in case you need this functionality in many views:

    [ValueConversion(typeof(bool), typeof(GridLength))]
    public class BoolToGridRowHeightConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return ((bool)value == true) ? new GridLength(1, GridUnitType.Star) : new GridLength(0);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {    // Don't need any convert back
            return null;
        }
    }

And then in the appropriate view <Grid.RowDefinition>:

<RowDefinition Height="{Binding IsHiddenRow, Converter={StaticResource BoolToGridRowHeightConverter}}"></RowDefinition>

Solution 2 - Wpf

The best and clean solution to collapse rows or columns is to use a DataTrigger so in your case:

<Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" MinHeight="30" />
      <RowDefinition Name="rowToHide">
        <RowDefinition.Style>
          <Style TargetType="{x:Type RowDefinition}">
            <Setter Property="Height" Value="Auto" />
            <Style.Triggers>
              <DataTrigger Binding="{Binding SomeBoolProperty}" Value="True">
                <Setter Property="Height" Value="0" />
              </DataTrigger>
            </Style.Triggers>
          </Style>
        </RowDefinition.Style>
      </RowDefinition>
      <RowDefinition Height="Auto" MinHeight="30" />
    </Grid.RowDefinitions>
  </Grid>

Solution 3 - Wpf

You can also do this by referencing the Row in the Grid and then changing the Height of the row itself.

XAML

<Grid Grid.Column="2" Grid.Row="1" x:Name="Links">
   <Grid.RowDefinitions>
      <RowDefinition Height="60" />
      <RowDefinition Height="*" />
      <RowDefinition Height="*" />
      <RowDefinition Height="80" />
   </Grid.RowDefinitions>
</Grid>

VB.NET

If LinksList.Items.Count > 0 Then
   Links.RowDefinitions(2).Height = New GridLength(1, GridUnitType.Star)
Else
   Links.RowDefinitions(2).Height = New GridLength(0)
End If

Whilst the Collapsing of the elements within the Grid also works, this is a bit simpler if you have many items in the Grid that does not have an enclosing element that can be collapsed. This would provide a good alternative.

Solution 4 - Wpf

For reference, Visibility is a three-state System.Windows.Visibility enumeration:

  • Visible - The element gets rendered and participates in layout.
  • Collapsed - The element is invisible and does not participate in layout. Effectively giving it a height and width of 0 and behaving as if it doesn't exist.
  • Hidden - The element is invisible but continues to participate in layout.

See this tip and other tips on the WPF Tips and Tricks thread.

Solution 5 - Wpf

Instead of fiddling with the Grid Row, you can set the Visibility property of the Controls (fields in the row) to "Collapsed". This will ensure that the controls don't take up any space and if you have Grid Row Height="Auto", then the row will be hidden as all the controls in the row have Visibility="Collapsed".

<Grid>
       <Grid.RowDefinitions>
         <RowDefinition Height="Auto" />
         <RowDefinition Height="Auto" Name="rowToHide" />
       </Grid.RowDefinitions>
    
   <Button Grid.Row=0 Content="Click Me" Height="20">
       <TextBlock Grid.Row=1 
Visibility="{Binding Converter={StaticResource customVisibilityConverter}}" Name="controlToHide"/>
    
</Grid>

This method is better because the Visibility of the controls can be bound to some property with the help of a Converter.

Solution 6 - Wpf

Simply do this:
rowToHide.Height = new GridLength(0);

if u will use visibility.Collapse then u have to set it for every member of the row.

Solution 7 - Wpf

Set the Row's content visibility to Visibility.Collapsed instead of Hidden. This will make the content stop taking up space, and the row will shrink appropriately.

Solution 8 - Wpf

I had a similar idea by inheriting RowDefinition (just for interest)

public class MyRowDefinition : RowDefinition
{
    private GridLength _height;

    public bool IsHidden
    {
        get { return (bool)GetValue(IsHiddenProperty); }
        set { SetValue(IsHiddenProperty, value); }
    }

    // Using a DependencyProperty as the backing store for IsHidden.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IsHiddenProperty =
        DependencyProperty.Register("IsHidden", typeof(bool), typeof(MyRowDefinition), new PropertyMetadata(false, Changed));

    public static void Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var o = d as MyRowDefinition;
        o.Toggle((bool)e.NewValue);
    }

    public void Toggle(bool isHidden)
    {
        if (isHidden)
        {
            _height = this.Height;
            this.Height = new GridLength(0, GridUnitType.Star);
        }                                                     
        else
            this.Height = _height;
    }          
}

Now you can use it as following:

 <Grid.RowDefinitions>
        <RowDefinition Height="2*" />
        <my:MyRowDefinition Height="4*" IsHidden="false" x:Name="RowToHide" />
        <RowDefinition Height="*" />
        <RowDefinition Height="60" />
    </Grid.RowDefinitions>

and toggle with

RowToHide.IsHidden = !RowToHide.IsHidden;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRichardView Question on Stackoverflow
Solution 1 - WpftestpatternView Answer on Stackoverflow
Solution 2 - WpfLukáš KotenView Answer on Stackoverflow
Solution 3 - WpfTravisPUKView Answer on Stackoverflow
Solution 4 - WpfMetro SmurfView Answer on Stackoverflow
Solution 5 - Wpfuser3726565View Answer on Stackoverflow
Solution 6 - WpfUSER_NAMEView Answer on Stackoverflow
Solution 7 - WpfReed CopseyView Answer on Stackoverflow
Solution 8 - WpfMattView Answer on Stackoverflow