如何在第二列内容可见时将Xaml网格列分成50/50?

3

如果有一个包含两列的网格,当第二列内容可见时,如何将其宽度分为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,否则第一列必须占据整个屏幕。
3个回答

4

创建一个转换器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 等。

0

这有点晚了,我自己也花了很长时间来寻找解决方案,但我希望通过我的回答方式,它将为未来的搜索者们更容易理解。(我正在使用WPF。)

最好的选择是将两个网格并排放置,并使它们占据彼此相关的一定空间,这需要从前两个答案中获取一些信息。

你需要:

  1. 2个ColumnDefinitions来定义宽度。
  2. 1个绑定,在代码后台通过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*”的总和)可用空间单位的部分。因此,如果我们将DG 1设置为“2*”,将DG 2设置为“5*”,则DG 1将自动占用2/7的空间,而DG 2将占用5/7的空间。这也适用于更多的DataGrid。

针对您的问题:

DataGrid 1的宽度始终为“*”。如果HasValue为true,则WidthDg2也为“*”,这将导致两个DataGrid各占用1/2的空间。如果HasValue为false,则WidthDg2将被设置为“0”,从而自动使DataGrid 1占用整个1个可用空间单位的空间,因为Datagrid不需要任何空间。


0

在宽度上使用星号,如下所示。如果有两个星号,它们将共享空间,但如果只有一个有内容,它应该填充第二个的空间。

<ColumnDefinition Width="*"/>


两列都会有内容,第二列可以显示/折叠。如果第二列的内容被折叠,我希望第一列占据第二列的空间。 - Lance

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