如何在WPF中折叠一个星号大小的网格列?

9

要使三列宽度相同,需要将Width设置为Auto

<Grid x:Name="myGrid">
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>

  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>

  <Label Grid.Row="0" Grid.Column="0">One</Label>
  <Label Grid.Row="0" Grid.Column="1" x:Name="label1">Two</Label>
  <Label Grid.Row="0" Grid.Column="2">Three</Label>
</Grid>

我希望实现的效果是,如果中间列被折叠或隐藏,其他两列将占据剩余空间并获得相等的宽度。
如果我只是将可见性设置为折叠或隐藏,由于宽度="*",其他两列的宽度保持不变。
<Label Grid.Row="0" Grid.Column="1" Visibility="Collapsed">Two</Label>

我通过编程将第二列的宽度设置为自动来实现所需功能,但我正在寻找其他解决方案(最好是一种XAML方式的解决方案)。

在此输入图片描述

private void Button_Click(object sender, RoutedEventArgs e)
{
  this.myGrid.ColumnDefinitions[1].Width = GridLength.Auto;
  this.label1.Visibility = Visibility.Collapsed;
}

1
我能想到的唯一使用XAML的方法是绑定。 - Robert
你可以相对于自身大小进行调整(星号大小/固定大小),也可以相对于内容大小进行调整(自动),但不能同时进行(星号大小,但如果宽度为0,则切换到自动)。你必须手动编写解决方案或创建自己的类似网格的控件来支持此功能。 - Ronan Thibaudau
1
请参阅 Code Project 上的 WPF Grid Column and Row Hiding。他们展示了一种仅使用绑定即可隐藏列的方法。 - ManDani
3个回答

10
所需的行为可以通过使用UniformGrid实现。
请确保将行数设置为1。
<UniformGrid Rows="1">
    <Label>One</Label>
    <Label>Two</Label>
    <Label>Three</Label>
</UniformGrid>

三列布局

其余元素均等间距排列。

<UniformGrid Rows="1">
    <Label>One</Label>
    <Label Visibility="Collapsed">Two</Label>
    <Label>Three</Label>
</UniformGrid>

2 cols


2

我按照Rob的建议添加了Xaml绑定,代码如下:

<Grid.ColumnDefinitions>
  <ColumnDefinition Width="*" />
  <ColumnDefinition Width="{Binding MiddleColumnWidth}" />
  <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

<Label Grid.Row="0" Grid.Column="0">One</Label>
<Label Grid.Row="0" Grid.Column="1" Visibility="{Binding IsSecondLabelVisible}">Two</Label>
<Label Grid.Row="0" Grid.Column="2">Three</Label>

XAML的代码后台:

private bool ShowOnlyTwoColumns;

private GridLength MiddleColumnWidth
{
  get
  {
    if (ShowOnlyTwoColumns)
      return GridLength.Auto; // Auto collapses the grid column when label is collapsed

    return new GridLength(1, GridUnitType.Star);
  }
}

private Visibility IsSecondLabelVisible
{
  get { return this.ShowOnlyTwoColumns ? Visibility.Collapsed : Visibility.Visible; }
}

0

我来晚了,但我想呈现我的解决方案,以防对任何人有用。

我使用这个转换器

public class BooleanToAutoOrStarGridLengthConverter : MarkupExtension, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is bool isStar)
            return new GridLength(1, isStar ? GridUnitType.Star : GridUnitType.Auto);
        return new GridLength(0, GridUnitType.Star);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is GridLength gridLength && gridLength.GridUnitType == GridUnitType.Star)
            return true;
        return false;
    }

    public override object ProvideValue(IServiceProvider serviceProvider) => this;
} 

在 XAML 中像这样:

<Grid.ColumnDefinitions>
  <ColumnDefinition Width="*" />
  <ColumnDefinition Width="{Binding IsSecondLabelVisible, Converter={BooleanToAutoOrStarGridLengthConverter}}" />
  <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

<Label Grid.Row="0" Grid.Column="0">One</Label>
<Label Grid.Row="0" Grid.Column="1" Visibility="{Binding IsSecondLabelVisible}">Two</Label>
<Label Grid.Row="0" Grid.Column="2">Three</Label>

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