Hide grid row in WPF
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 hidde开发者_Go百科n already.
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>
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>
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.
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.
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.
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.
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.
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;
精彩评论