从C#代码动态切换WPF网格列的可见性

31

我的问题是:我不知道如何切换WPF网格列的可见性。假设以下XAML标记:

<Grid x:Name="myGrid">
    <Grid.RowDefinitions>
        <RowDefinition x:Name="Row1" />
        <RowDefinition x:Name="Row2" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition x:Name="Column1" />
        <ColumnDefinition x:Name="Column2" />
    </Grid.ColumnDefinitions>
</Grid>

在填充一些控件后,我想要在我的C#代码中动态隐藏单列。我尝试通过将列定义宽度设置为零来实现这一点,例如: Column1.Width = 0。这个方法可行,但我并不是很喜欢 - 是否真的没有更好的方法?
我正在寻找类似于 myGrid.Columns[0].Visibility = COLLAPSEDColumn1.Visibility = HIDDEN 的内容。我找不到类似的内容 - 有什么建议吗?

@DaveRook 当然可以做到 - 我只是好奇是否有一种不需要这样的hack的简单方法。 - sebi
你希望该列中的控件发生什么事情? - Dave
@DaveRook 当我折叠列时,我也想折叠所有包含的控件 - 所以整个列,包括内容,都应该是不可见的。 - sebi
可能是WPF中隐藏网格行的重复问题。 - Palec
5个回答

44
<ColumnDefinition>
  <ColumnDefinition.Style>
    <Style TargetType="ColumnDefinition">
      <Setter Property="Width" Value="*" />
        <Style.Triggers>
          <DataTrigger Binding="{Binding IsColumnVisible}" Value="False">
            <Setter Property="Width" Value="0" />
          </DataTrigger>
        </Style.Triggers>
    </Style>
  </ColumnDefinition.Style>
</ColumnDefinition>
请在您的ViewModel中实现INotifyPropertyChanged。

2
如果您想要列的动态可见性,这是正确的方法。 - Lennart
3
@Lennart同意了,这应该是被认可的解决方案。 - rschoenbach
1
简单而清晰。我同意这应该是被接受的答案,因为它提供了相当多的灵活性,并允许用户坚持MVVM。 - Grahamvs
我对WPF很新,我应该将其应用于所有列定义吗?因为我的每一列都有自己的宽度。那么我应该做什么? - Harxish
1
@Harxish 如果你想的话可以这样做。然而,如果列数太多,不会影响用户体验吗?用户将不得不应对水平滚动。 - Morlo Mbakop

14

最简单的方法是在你想要隐藏的相关列中添加一个命名为Grid的控件作为顶层控件。然后,你可以像隐藏其他控件一样来隐藏它及其所有内容:

XAML代码如下:

<Grid x:Name="myGrid">
    <Grid.RowDefinitions>
        <RowDefinition x:Name="Row1" />
        <RowDefinition x:Name="Row2" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition x:Name="Column1" />
        <ColumnDefinition x:Name="Column2" />
    </Grid.ColumnDefinitions>
    <Grid x:Name="GridColumn1" Grid.Column="1">
        ...
    </Grid>
</Grid>

然后在代码后台:

GridColumn1.Visibility = Visibility.Collapsed;

如果你的网格(Grid)中有多行,你可能想要像这样重新排列它们:

<Grid x:Name="myGrid">
    <Grid.ColumnDefinitions>
        <ColumnDefinition x:Name="Column1" />
        <ColumnDefinition x:Name="Column2" />
    </Grid.ColumnDefinitions>
    <Grid x:Name="GridColumn0" Grid.Column="0">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
    </Grid>
    <Grid x:Name="GridColumn1" Grid.Column="1">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
    </Grid>
</Grid>

更新 >>>

实际上没有必要像这样重新排列主 Grid,您可以很容易地添加两个 Grid 控件,在相关列的每一行中各添加一个,然后同时设置它们的 Visibility 属性:

InnerGrid1.Visibility = InnerGrid2.Visibility = Visibility.Collapsed;

您甚至可以将一个Grid添加到主要Grid的每个单元格中,并完全控制任何时候可见的单元格。


是的,我想我必须重新排列XAML代码以实现我想要的方式 - 尽管这是我试图避免的事情,因为这是一些同事的大量代码..无论如何,还是谢谢 :) - sebi
即使您想同时隐藏列和行,但如果这样做会导致问题,您仍然需要处理。 - sebi
仅当行/列的高度/宽度设置为“自动”时,折叠行/列中的所有元素才会折叠该行/列。如果您想要折叠,请查看:https://www.codeproject.com/articles/437237/wpf-grid-column-and-row-hiding。 - David

7

在Code Project的WPF网格列和行隐藏中,他们展示了一种使用依赖属性的方法。他们设置 Visible = false, 但内部实际上将其设置为 Width = 0

另一个想法是在代码后台删除列定义...但我认为这甚至更糟糕!:(


2
我尝试删除列定义本身:网格正确重新排列,但是列的内容仍然存在(元素重叠)...但还是谢谢;) - sebi

3

一种丑陋的解决方法是将宽度更改为0(看不见,就不会想)。

有许多原因不应该这样做,但根据您的情况,这可能足够!


2
你能否分享一些原因,为什么仅将高度设置为零是一个不好的想法? - Palec
如果该行可调整大小,您可能希望保存和恢复该大小,但同时设置为0高度即可。 - Denise Skidmore

-11

使用以下代码隐藏网格。同样,您也可以使用Name属性隐藏行定义和列定义。

myGrid.Visibility = System.Windows.Visibility.Hidden;


5
只需隐藏一个列,而不是整个网格。 - jpierson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接