隐藏WPF中的网格行

Ric*_*ard 91 wpf grid

我有一个简单的WPF表单,在表单上Grid声明.这Grid有一堆行:

<Grid.RowDefinitions>
    <RowDefinition Height="Auto" MinHeight="30" />
    <RowDefinition Height="Auto" Name="rowToHide" />
    <RowDefinition Height="Auto" MinHeight="30" />
</Grid.RowDefinitions>
Run Code Online (Sandbox Code Playgroud)

命名行rowToHide包含一些输入字段,我想在检测到我不需要这些字段后隐藏这一行.它很简单,只需设置Visibility = Hidden行中的所有项目,但该行仍占用空间Grid.我尝试设置Height = 0项目,但似乎没有用.

你可以这样想:你有一个表格,在那里你有一个下拉说"付款类型",如果这个人选择"现金",你想要隐藏包含卡详细信息的行.这个隐藏的表单不是一个选项.

tes*_*ern 81

Row没有Visibility属性,正如其他人所说,你需要设置高度.另一种选择是使用转换器,以防您在许多视图中需要此功能:

    [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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

然后在适当的视图中<Grid.RowDefinition>:

<RowDefinition Height="{Binding IsHiddenRow, Converter={StaticResource BoolToGridRowHeightConverter}}"></RowDefinition>
Run Code Online (Sandbox Code Playgroud)

  • UpVoted - 转换器允许所有这些在Xaml中声明.我一般不喜欢使用代码隐藏来摆弄视觉效果. (10认同)
  • 很好的答案。我假设您指的是 IsDisplayedRow,而不是 IsHiddenRow。 (2认同)

Luk*_*ten 66

折叠行或列的最佳和干净的解决方案是使用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>
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这种方法,因为你不需要额外的C#代码. (5认同)
  • 不要忘记在后面的代码中实现“INotifyPropertyChanged”,以便在“SomeBoolProperty”更改时它可以工作:)。 (2认同)

Tra*_*PUK 53

您也可以通过引用网格中的行然后更改行本身的高度来执行此操作.

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>
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

虽然网格中元素的折叠也有效,但如果网格中有许多项目没有可折叠的封闭元素,则会更简单一些.这将提供一个很好的选择.

  • 这也有利用使用星形符号的行的优势! (2认同)
  • 我不认为这是最清晰,最易读的解决方案,因为功能代码分为两个独立的文件.事实上,所有这一切都可以用纯XAML完成 - 请参阅我的回答. (2认同)

Met*_*urf 29

供参考,Visibility是一个三态System.Windows.Visibility枚举:

  • 可见 - 元素被渲染并参与布局.
  • 折叠 - 元素不可见,不参与布局.有效地给它一个0的高度和宽度,并表现得好像它不存在.
  • 隐藏 - 元素不可见但继续参与布局.

有关WPF提示和技巧主题的信息,请参阅此提示和其他提示.

  • @testpattern - downvotes通常用于不正确的答案.如果其他答案更好,只需投票即可. (11认同)
  • @MetroSmurf足够公平.可以说,你的答案是不正确的,因为RowDefinition没有Visibility属性.TravisPUK展示了如何隐藏行,这应该是接受的答案. (6认同)

小智 8

您可以将Controls的Visibility属性(行中的字段)设置为"Collapsed",而不是摆弄Grid Row.这将确保控件不占用任何空间,如果您有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>
Run Code Online (Sandbox Code Playgroud)

此方法更好,因为控件的可见性可以在Converter的帮助下绑定到某些属性.


USE*_*AME 7

只需这样做:
rowToHide.Height = new GridLength(0);

如果你将使用,visibility.Collapse那么你必须为该行的每个成员设置它.


Mat*_*att 7

我通过继承 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;
    }          
}
Run Code Online (Sandbox Code Playgroud)

现在您可以按如下方式使用它:

 <Grid.RowDefinitions>
        <RowDefinition Height="2*" />
        <my:MyRowDefinition Height="4*" IsHidden="false" x:Name="RowToHide" />
        <RowDefinition Height="*" />
        <RowDefinition Height="60" />
    </Grid.RowDefinitions>
Run Code Online (Sandbox Code Playgroud)

并切换

RowToHide.IsHidden = !RowToHide.IsHidden;
Run Code Online (Sandbox Code Playgroud)


Ree*_*sey 5

将行的内容可见性设置为Visibility.Collapsed而不是隐藏。这将使内容停止占用空间,并且行将适当缩小。

  • @Richard:您不能设置RowDefinition.Visibility,因为它不是UIElement-但您可以将行(或行中的每一列)的所有内容放入单个容器中,并设置该容器的可见性。 (5认同)