在 WPF 中隐藏网格行

Posted

技术标签:

【中文标题】在 WPF 中隐藏网格行【英文标题】:Hide grid row in WPF 【发布时间】:2011-01-30 22:11:56 【问题描述】:

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

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

【问题讨论】:

请参阅关于 Visibility 作为 3 状态系统的提示(在 WPF 提示线程中):***.com/questions/860193/wpf-simple-tips-and-tricks/… 很棒的东西......如果你把它作为答案我会标记...... 也看看这个技巧:social.msdn.microsoft.com/Forums/en-US/wpf/thread/… 【参考方案1】:

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

【讨论】:

我在其他地方看到有人提到了行可见性。但是 Row 没有可见性状态?将行中的所有项目设置为 Visibility.Collapsed 仍然有效。 @Richard:您无法设置 RowDefinition.Visibility 因为它不是 UIElement - 但您可以将行(或行中的每一列)的所有内容放入单个容器中,并且设置该容器的可见性。 如果你的网格行没有任何内容,而是固定高度怎么办?有没有方便的显示/隐藏方式?【参考方案2】:

作为参考,Visibility 是一个三态的System.Windows.Visibility 枚举:

可见 - 元素被渲染并参与布局。 Collapsed - 元素不可见且不参与布局。有效地将其高度和宽度设为 0,并表现得好像它不存在一样。 隐藏 - 元素不可见,但继续参与布局。

请参阅this tip 和WPF Tips and Tricks 线程上的其他提示。

【讨论】:

将行中的所有项目设置为 Visibility.Collapsed 工作,谢谢。 我对此投了反对票,因为我认为@TravisPUK 的答案包含一个更清晰、更明显的解决方案。 @testpattern - 否决票通常用于错误答案。如果其他答案更好,请点赞。 @MetroSmurf 很公平。可以说,您的答案不正确,因为 RowDefinition 没有可见性属性。 TravisPUK 展示了如何隐藏一行,这应该是公认的答案。【参考方案3】:

您也可以通过引用网格中的行然后更改行本身的高度来做到这一点。

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 中有许多项目没有可以折叠的封闭元素,这会更简单一些。这将提供一个很好的选择。

【讨论】:

这还具有处理使用星号表示法的行的优点! 在代码中执行此操作是最清晰、最易读的解决方案。也许在RowDefinition 之后添加评论,例如&lt;RowDefinition Height="*" /&gt;&lt;!-- Height set in code behind --&gt; 我不认为这是最清晰和最易读的解决方案,因为功能代码分为两个单独的文件。事实上,这一切都可以用纯 XAML 完成 - 请参阅我的答案。 我的需求在 C# 中有所不同,但这个示例为我指明了正确的方向。谢谢!【参考方案4】:

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

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

【讨论】:

【参考方案5】:

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;
        
    

然后在适当的视图&lt;Grid.RowDefinition&gt;:

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

【讨论】:

UpVoted - 转换器允许在 Xaml 中声明所有这些。我通常讨厌使用代码隐藏来摆弄视觉内容。 这非常有用,可以轻松扩展。我建议调用它BoolToGridLengthConverter 并添加一个VisibleLength-Property,以返回(bool)value == true。这就是您还可以使用 Auto 和任何修复值重用它的方法。 很好的答案。我假设您的意思是 IsDisplayedRow,而不是 IsHiddenRow。【参考方案6】:

我通过继承 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;

【讨论】:

【参考方案7】:

您可以将控件(行中的字段)的 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>

这种方法更好,因为控件的可见性可以在转换器的帮助下绑定到某些属性。

【讨论】:

【参考方案8】:

折叠行或列的最佳且干净的解决方案是在您的情况下使用 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>

【讨论】:

我喜欢这种方法,因为您不需要额外的 C# 代码。 不要忘记在您的代码中实现INotifyPropertyChanged,以便在更改SomeBoolProperty 时它可以工作:)。

以上是关于在 WPF 中隐藏网格行的主要内容,如果未能解决你的问题,请参考以下文章

在 WPF Datagrid 中为网格线着色

如何通过 C# WPF 在 Excel 工作表中隐藏网格线

WPF:动态隐藏网格列并不总是使用 Styles 或 IValueConverter 正常工作

WPF 中网格的隐式行定义

在WPF中更改网格行背景颜色

在wpf中将treeviewitem显示为网格行