Скрыть строку сетки в WPF
У меня есть простая форма WPF с Grid
заявлено на бланке. это Grid
имеет ряд строк:
<Grid.RowDefinitions>
<RowDefinition Height="Auto" MinHeight="30" />
<RowDefinition Height="Auto" Name="rowToHide" />
<RowDefinition Height="Auto" MinHeight="30" />
</Grid.RowDefinitions>
Строка имени rowToHide
содержит несколько полей ввода, и я хочу скрыть эту строку после того, как обнаружу, что эти поля мне не нужны. Достаточно просто установить Visibility = Hidden
для всех элементов в строке, но строка все еще занимает место в Grid
, Я пробовал настройку Height = 0
к предметам, но это не сработало.
Вы можете думать об этом так: у вас есть форма, там у вас есть выпадающий список с надписью "Тип платежа", и если человек выбирает "Наличные", вы хотите скрыть строку, содержащую данные карты. Это не вариант, чтобы начать форму с этим скрытым уже.
8 ответов
Вы также можете сделать это, ссылаясь на строку в сетке, а затем изменив высоту самой строки.
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
Хотя свертывание элементов в Grid также работает, это немного проще, если в Grid есть много элементов, в которых нет включающего элемента, который можно свернуть. Это обеспечит хорошую альтернативу.
Строка не имеет свойства видимости, поэтому, как говорили другие, вам нужно установить высоту. Другой вариант - использовать конвертер, если вам нужна эта функциональность во многих представлениях:
[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;
}
}
И тогда в соответствующем представлении <Grid.RowDefinition>
:
<RowDefinition Height="{Binding IsHiddenRow, Converter={StaticResource BoolToGridRowHeightConverter}}"></RowDefinition>
Лучшее и чистое решение для свертывания строк или столбцов - использовать DataTrigger, поэтому в вашем случае:
<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>
Для справки, Visibility
перечисление System.Windows.Visibility с тремя состояниями:
- Видимый - элемент визуализируется и участвует в макете.
- Свернутый - элемент невидим и не участвует в макете. Эффективно присваивая ему высоту и ширину 0 и ведя себя так, как будто его не существует.
- Скрытый - элемент невидим, но продолжает участвовать в макете.
См. Этот совет и другие советы в ветке WPF Tips and Tricks.
Вместо того, чтобы возиться со строкой сетки, вы можете установить для свойства "Видимость" элементов управления (полей в строке) значение "Свернутый". Это гарантирует, что элементы управления не занимают никакого пространства, и если у вас Grid Row Height = "Auto", строка будет скрыта, поскольку все элементы управления в строке имеют 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>
Этот метод лучше, потому что видимость элементов управления может быть связана с некоторым свойством с помощью конвертера.
Просто сделайте это:rowToHide.Height = new GridLength(0);
если ты будешь использовать visibility.Collapse
тогда вы должны установить его для каждого члена строки.
Установите видимость содержимого строки в Visibility.Collapsed
вместо скрытого. Это заставит контент перестать занимать место, и строка будет соответственно уменьшена.
У меня была похожая идея, унаследовав RowDefinition (просто для интереса)
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;
}
}
Теперь вы можете использовать его следующим образом:
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<my:MyRowDefinition Height="4*" IsHidden="false" x:Name="RowToHide" />
<RowDefinition Height="*" />
<RowDefinition Height="60" />
</Grid.RowDefinitions>
и переключаться с
RowToHide.IsHidden = !RowToHide.IsHidden;