当第二列的内容可见时,如何拆分 Xaml 网格列 50/50?
How to split Xaml Grid column 50/50 when the 2nd column's content is visible?
对于具有 2 列的网格,如何才能仅在第二列的内容可见时将其按 50/50 的宽度拆分?
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<!-- Some content here -->
</Grid>
<Grid Grid.Column="1" Visibility="{Binding HasValue, Converter={StaticResource BooleanToVisibilityConverter}}">
<!-- Some content here -->
</Grid>
</Grid>
如果HasValue
为真,网格需要50/50分割,否则,第一列必须占据整个屏幕。
使用星号表示宽度,如下所示。如果你有两个,他们会分享,但如果只有一个有内容,它应该填充第二个的 space。
<ColumnDefinition Width="*"/>
创建转换器 BoolToGridLengthConverter 并将其作为静态资源放入您的 App.xaml
中:
/// <summary>
/// Converts a boolean value to a grid length which is specified with a converter
/// parameter if the value is true, otherwise the grid lengthe will be zero.
/// <para>
/// If no parameter is specified the returned <see cref="Windows.UI.Xaml.GridLength"/> will be zero.
/// If the parameter cannot be parsed to a grid length then the returned <see cref="Windows.UI.Xaml.GridLength"/> will be zero.
/// If the value is a <see cref="bool"/> false, then the returned <see cref="Windows.UI.Xaml.GridLength"/> will be zero.
/// </para>
/// </summary>
public sealed class BoolToGridLengthConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (!(value is bool) || !(parameter is string))
{
return new GridLength(0);
}
if (!((bool)value))
{
return new GridLength(0);
}
var str = parameter as string;
if (str.Equals("Auto"))
{
return new GridLength(0, GridUnitType.Auto);
}
if (str.Equals("*"))
{
return new GridLength(1, GridUnitType.Star);
}
if (str.EndsWith("*"))
{
var length = Double.Parse(str.Substring(0, str.Length - 1));
return new GridLength(length, GridUnitType.Star);
}
var len = Double.Parse(str);
return new GridLength(len);
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
然后您可以像这样在 xaml 中使用它:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="{Binding HasValue, Converter={StaticResource BoolToGridLengthConverter}, ConverterParameter='*'}"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<!-- Some content here -->
</Grid>
<Grid Grid.Column="1" Visibility="{Binding HasValue, Converter={StaticResource BooleanToVisibilityConverter}}">
<!-- Some content here -->
</Grid>
</Grid>
仅当布尔值为 true
时,转换器才会使用 ConverterParameter
,否则列宽将设置为零。转换器参数,可以是 Auto
,或者例如 0.5*
或任何固定宽度例如 50.5
等
这有点晚了,我自己不得不搜索很长时间才能找到解决方案,但我希望通过我回答的方式,它是可以理解的或未来的搜索者。 (我正在使用 WPF。)
将两个网格并排放置并让它们占据彼此相关的某个 space 的最佳选择取自上面的 2 个答案。
你需要:
- 2 个定义宽度的 ColumnDefinitions。
- 1 Binding,由HasValue-Binding在代码隐藏中设置。
在XAML中:
<Grid>
<Grid.ColumnDefinition>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width={Binding WidthDg2}/>
<Grid.ColumnDefinition/>
<DataGrid Grid.Column="0" ...>
<DataGrid.Columns>
...
<DataGrid.Columns/>
<DataGrid/>
<DataGrid Grid.Column="1" Visibility={Binding HasValue}>
<DataGrid.Columns>
...
<DataGrid.Columns/>
<DataGrid/>
<Grid/>
在 C# 代码中:
...
#region Properties
private Boolean _hasValue;
public Boolean HasValue
{
get => _hasValue;
set
{
_hasValue = value;
OnPropertyChanged();
}
}
private string _widthDg2;
public string WidthDg2
{
get => HasValue ? "*" : "0";
set
{
_widthDg2 = value;
OnPropertyChanged();
}
}
#endregion Properties
...
上下文:
DataGrid (DG) 的宽度将始终是其“x*”,这意味着 x(自然数或 0)部分 y(所有“x*”的总和)可用 space 个单位.因此,如果我们将 DG 1 设置为“2*”,将 DG 2 设置为“5*”,DG 1 将自动占用 space 的 2/7,而 DG 2 将占用 5/7。这也适用于更多 DataGrids。
针对您的问题:
DataGrid 1 的宽度始终为“*”。如果 HasValue 为真,WidthDg2 也为“*”,这将导致两个 DataGrid 各占 1/2 space。如果 HasValue 为假,WidthDg2 将被设置为“0”,自动导致 DataGrid 1 占用整个 1 个单位的 1 个可用 space 单元,因为 Datagrid 需要 0 space.
对于具有 2 列的网格,如何才能仅在第二列的内容可见时将其按 50/50 的宽度拆分?
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<!-- Some content here -->
</Grid>
<Grid Grid.Column="1" Visibility="{Binding HasValue, Converter={StaticResource BooleanToVisibilityConverter}}">
<!-- Some content here -->
</Grid>
</Grid>
如果HasValue
为真,网格需要50/50分割,否则,第一列必须占据整个屏幕。
使用星号表示宽度,如下所示。如果你有两个,他们会分享,但如果只有一个有内容,它应该填充第二个的 space。
<ColumnDefinition Width="*"/>
创建转换器 BoolToGridLengthConverter 并将其作为静态资源放入您的 App.xaml
中:
/// <summary>
/// Converts a boolean value to a grid length which is specified with a converter
/// parameter if the value is true, otherwise the grid lengthe will be zero.
/// <para>
/// If no parameter is specified the returned <see cref="Windows.UI.Xaml.GridLength"/> will be zero.
/// If the parameter cannot be parsed to a grid length then the returned <see cref="Windows.UI.Xaml.GridLength"/> will be zero.
/// If the value is a <see cref="bool"/> false, then the returned <see cref="Windows.UI.Xaml.GridLength"/> will be zero.
/// </para>
/// </summary>
public sealed class BoolToGridLengthConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (!(value is bool) || !(parameter is string))
{
return new GridLength(0);
}
if (!((bool)value))
{
return new GridLength(0);
}
var str = parameter as string;
if (str.Equals("Auto"))
{
return new GridLength(0, GridUnitType.Auto);
}
if (str.Equals("*"))
{
return new GridLength(1, GridUnitType.Star);
}
if (str.EndsWith("*"))
{
var length = Double.Parse(str.Substring(0, str.Length - 1));
return new GridLength(length, GridUnitType.Star);
}
var len = Double.Parse(str);
return new GridLength(len);
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
然后您可以像这样在 xaml 中使用它:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="{Binding HasValue, Converter={StaticResource BoolToGridLengthConverter}, ConverterParameter='*'}"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<!-- Some content here -->
</Grid>
<Grid Grid.Column="1" Visibility="{Binding HasValue, Converter={StaticResource BooleanToVisibilityConverter}}">
<!-- Some content here -->
</Grid>
</Grid>
仅当布尔值为 true
时,转换器才会使用 ConverterParameter
,否则列宽将设置为零。转换器参数,可以是 Auto
,或者例如 0.5*
或任何固定宽度例如 50.5
等
这有点晚了,我自己不得不搜索很长时间才能找到解决方案,但我希望通过我回答的方式,它是可以理解的或未来的搜索者。 (我正在使用 WPF。)
将两个网格并排放置并让它们占据彼此相关的某个 space 的最佳选择取自上面的 2 个答案。
你需要:
- 2 个定义宽度的 ColumnDefinitions。
- 1 Binding,由HasValue-Binding在代码隐藏中设置。
在XAML中:
<Grid>
<Grid.ColumnDefinition>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width={Binding WidthDg2}/>
<Grid.ColumnDefinition/>
<DataGrid Grid.Column="0" ...>
<DataGrid.Columns>
...
<DataGrid.Columns/>
<DataGrid/>
<DataGrid Grid.Column="1" Visibility={Binding HasValue}>
<DataGrid.Columns>
...
<DataGrid.Columns/>
<DataGrid/>
<Grid/>
在 C# 代码中:
...
#region Properties
private Boolean _hasValue;
public Boolean HasValue
{
get => _hasValue;
set
{
_hasValue = value;
OnPropertyChanged();
}
}
private string _widthDg2;
public string WidthDg2
{
get => HasValue ? "*" : "0";
set
{
_widthDg2 = value;
OnPropertyChanged();
}
}
#endregion Properties
...
上下文:
DataGrid (DG) 的宽度将始终是其“x*”,这意味着 x(自然数或 0)部分 y(所有“x*”的总和)可用 space 个单位.因此,如果我们将 DG 1 设置为“2*”,将 DG 2 设置为“5*”,DG 1 将自动占用 space 的 2/7,而 DG 2 将占用 5/7。这也适用于更多 DataGrids。
针对您的问题:
DataGrid 1 的宽度始终为“*”。如果 HasValue 为真,WidthDg2 也为“*”,这将导致两个 DataGrid 各占 1/2 space。如果 HasValue 为假,WidthDg2 将被设置为“0”,自动导致 DataGrid 1 占用整个 1 个单位的 1 个可用 space 单元,因为 Datagrid 需要 0 space.