【问题标题】:How to split Xaml Grid column 50/50 when the 2nd column's content is visible?当第二列的内容可见时,如何将 Xaml Grid 列拆分为 50/50?
【发布时间】:2015-08-28 19:06:09
【问题描述】:

对于一个有 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 分割,否则第一列必须占据整个屏幕。

【问题讨论】:

    标签: c# xaml windows-runtime grid


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      使用星号表示宽度,如下所示。如果你有两个,他们会分享,但如果只有一个有内容,它应该填满第二个的空间。

      &lt;ColumnDefinition Width="*"/&gt;

      【讨论】:

      • 两列都有内容,第二列可以显示/折叠。如果第二列的内容被折叠,我希望第一列占据第二列空间。
      【解决方案3】:

      这有点晚了,我自己不得不搜索很长时间才能找到解决方案,但我希望通过我回答它的方式,这将是可以理解的或未来的搜索者。 (我正在使用 WPF。)

      最好的选择是让两个网格并排,并让它们占据一定的相互关联的空间,这需要从上面的 2 个答案中获取一些信息。

      你需要:

      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*”,这意味着 y(所有“x*”的总和)可用空间单位的 x(自然数或 0)部分。因此,如果我们将 DG 1 设置为“2*”,将 DG 2 设置为“5*”,则 DG 1 将自动占用 2/7 的空间,DG 2 将占用 5/7。这也适用于更多 DataGrid。

      针对您的问题:

      DataGrid 1 的宽度始终为“*”。如果 HasValue 为真 WidthDg2 也是“*”,这将导致两个 DataGrid 各占用 1/2 空间。如果 HasValue 为 false WidthDg2 将设置为“0”,自动导致 DataGrid 1 占用 1 个可用空间单元的全部 1 个单元,因为 Datagrid 需要 0 个空间。

      【讨论】:

        猜你喜欢
        • 2022-11-08
        • 1970-01-01
        • 1970-01-01
        • 2014-06-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多