如何在WPF中折叠星形大小的网格列?

问题描述 投票:0回答:4

通过将

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;
}
wpf xaml wpf-grid
4个回答
11
投票

可以使用

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
投票

我按照 Rob 的建议添加了 Xaml Binding,如下所示:

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

0
投票

我最终得到了类似于h.m.i.13答案的想法。我创建了一个通用转换器,它隐藏列/行或使用特定的网格长度值显示它。 优点是它可以处理更复杂的网格,其中并非每行都有简单的一星长度。

public class BooleanToGridLengthConverter : IValueConverter
{
    private readonly static GridLength DefaultLength = new GridLength(0, GridUnitType.Pixel);

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is not bool booleanValue ||
            parameter is not string stringParameter)
        {
            return DefaultLength;
        }

        if (booleanValue && TryParseGridLength(stringParameter, out var gridLength))
        {
            return gridLength;
        }

        return DefaultLength;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    private static bool TryParseGridLength(string stringValue, out GridLength gridLength)
    {
        gridLength = DefaultLength;

        if (stringValue.Equals("Auto", StringComparison.OrdinalIgnoreCase))
        {
            gridLength = GridLength.Auto;
            return true;
        }

        if (stringValue.EndsWith("*"))
        {
            double starCount = 1;
            if (stringValue.Length > 1 && !double.TryParse(stringValue.AsSpan(0, stringValue.Length - 1), out starCount))
            {
                return false;
            }

            gridLength  = new GridLength(starCount, GridUnitType.Star);
            return true;
        }

        if (double.TryParse(stringValue, out var pixelValue))
        {
            gridLength = new GridLength(pixelValue, GridUnitType.Pixel);
            return true;
        }

        return false;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.