通过将
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;
}
我按照 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; }
}
我迟到了,但我想展示我的解决方案,以防它对任何人有用。
我用这个转换器
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>
我最终得到了类似于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;
}
}