在WPF中隐藏网格行


94

我有一个简单的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项目,但这似乎不起作用。

您可以这样想:您有一个表格,在其中有一个下拉菜单,显示“付款类型”,如果此人选择了“现金”,则想隐藏包含卡详细信息的行。不能在已隐藏的情况下启动表单。


1
看到上能见度是一个3态系统(在WPF提示线程)这提示:stackoverflow.com/questions/860193/wpf-simple-tips-and-tricks/...
地铁蓝精灵

很棒的东西...如果您把它作为一个答案,我会标记为...
理查德(Richard)2010年

Answers:


88

Row没有Visibility属性,因此正如其他人所说,您需要设置Height。如果在许多视图中需要此功能,则另一个选择是使用转换器:

    [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>

10
UpVoted-转换器允许所有这些都在Xaml中进行声明。我通常讨厌使用后台代码来摆弄视觉化的东西。
艾伦

1
这非常有用,可以轻松扩展。我建议调用它BoolToGridLengthConverter并添加VisibleLength-Property以返回(bool)value == true。这就是您还可以将其与Auto任何Fix-Value 重用的方法。
LuckyLikey

1
好答案。我假设您的意思是IsDisplayedRow,而不是IsHiddenRow。
NielW '18

72

折叠行或列的最佳和干净的解决方案是使用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>

5
我喜欢这种方法,因为您不需要附加的C#代码。
user11909

1
不要忘了INotifyPropertyChanged在代码中实现它,以使其在SomeBoolProperty更改时起作用:)。
benichka '18

55

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

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

尽管也可以折叠网格中的元素,但是如果网格中有很多项目没有可折叠的封闭元素,则这会更简单。这将提供一个很好的选择。


2
这也具有使用星号表示法的行的优势!
Johny Skovdal 2012年

1
用代码执行此操作是最清晰,最易读的解决方案。也许在后面添加评论RowDefinition,例如<RowDefinition Height="*" /><!-- Height set in code behind -->
Kay Zed

2
我认为这不是最清晰,最易读的解决方案,因为功能代码分为两个单独的文件。实际上,所有这些都可以使用纯XAML完成-请参阅我的答案。
卢卡斯Koten

我的需求有所不同,在C#中,但此示例为我指明了正确的方向。谢谢!
nrod

30

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

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

请参阅WPF技巧和窍门线程上的此技巧和其他技巧。


1
将行中的所有项目都设置为Visibility.Collapsed起作用了,谢谢。
理查德(Richard)2010年

1
我对此表示反对,因为我认为@TravisPUK的答案包含一个更清晰,更明显的解决方案。
testpattern 2014年

11
@testpattern-下注通常用于错误答案。如果另一个答案更好,那就投票吧。
大都会蓝精灵

6
@MetroSmurf足够公平。可以说,您的答案是不正确的,因为RowDefinition没有Visibility属性。TravisPUK显示了如何隐藏行,这应该是公认的答案。
testpattern 2014年

8

您可以将控件的“可见性”属性(行中的字段)设置为“ Collapsed”,而不必摆弄“网格行”。这将确保控件不占用任何空间,并且如果您具有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>

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


7

只需执行以下操作:
rowToHide.Height = new GridLength(0);

如果您要使用,visibility.Collapse则必须为该行的每个成员进行设置。


6

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


1
我在其他地方看到有人提到行可见性。但是“行”没有可见性状态?将行中的所有项目设置为Visibility.Collapsed可以正常工作。
理查德

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

1
如果您的网格行不包含任何内容,但是高度固定,该怎么办?有显示/隐藏的便捷方法吗?
kevinarpe 2012年

4

我通过继承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;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.