Skip to content

Feature Proposal: Make Grid Better #54

@micahl

Description

@micahl

Proposal: Grid - More gain, less pain

Summary

Make a version of Grid that is easier to use and manipulate with capabilities that are on par with the CSS Grid.

Rationale

XAML's Grid is the most widely used Panel and is very versatile. However, it's also one of the more complicated panels and can be cumbersome. It doesn't lend itself well to easily positioning elements or simple adjustments (e.g. inserting a new row/column). Enhancing the Grid in a few simple ways will go a long way towards easing a developer's job.

Functional Requirements

# Feature Priority
1 Able to refer to rows / columns by either number or a name Must
2 Able to define spans as relative numbers or using names Must
3 Able to assign a friendly name to a region of the grid and associate child element's with that region by name versus the row(span)/col(span) #'s Could
4 Able to more succinctly define rows / columns, with options to be more explicit Should
5 Support auto flow where some items may be explicitly assigned and the rest implicitly fill in by tree order (with control over how it auto fills) Should
6 Support for defining auto-generated rows/columns that are implicitly created to position items with otherwise out-of-bounds grid indices Should
7 Support alignment options for a general policy that applies to all the Grid's children (individual elements can override) Could
8 Support a ShowGridLines property to aid in visual debugging the layout Could

Usage Examples

Named Row / Column

<Grid>
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="1*"/>
    <RowDefinition Name="bottomrow" Height="Auto"/>
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition Width="1*"/>
    <ColumnDefinition Name="rightcol" Width="Auto"/>
  </Grid.ColumnDefinitions>

  <Button Grid.Row="bottomrow" Grid.Column="rightcol"/>

</Grid>

A More Succinct Syntax

<Grid RowDefinitions="Auto, 1*, {Name=bottomrow Width=Auto}"
      ColumnDefinitions="Auto, 1*, {Name=rightcol Width=Auto}">

  <Button Grid.Row="bottomrow" Grid.Column="rightcol"/>

</Grid>

Defining Named Areas
Specify a single Row (or Column) using just the name or the index. You can optionally provide a span by name or relative count with the comma syntax "fromRow,toRow" or "fromRow,#".

<Grid ColumnDefinitions="{Name=leftcol Width=Auto}, 1*, {Name=rightcol Width=Auto}"
      RowDefinitions="{Name=toprow Width=Auto}, {Name=body Width=1*}, {Name=bottomrow Width=Auto}">
      <Grid.AreaDefinitions>
        <AreaDefinition Name="imageArea" Row="toprow,bottomrow" Column="0"/>
        <AreaDefinition Name="header" Row="toprow" Column="leftcol,rightcol"/>
        <AreaDefinition Name="footer" Row="bottomrow" Column="leftcol,rightcol"/>
      <Grid.AreaDefinitions>

      <Image Grid.Area="imageArea"/>

      <TextBlock Grid.Area="Header"/>

      <Button Grid.Row="bottomrow" Grid.Column="rightcol"/>
</Grid>

More Succinctly Defined Areas

<Grid ColumnDefinitions="{Name=leftcol Width=Auto}, 1*, {Name=rightcol Width=Auto}"
      RowDefinitions="{Name=toprow Width=Auto}, {Name=body Width=1*}, {Name=bottomrow Width=Auto}"
      AreaDefinitions="{Name=imageArea Row=toprow,bottomrow Column=0},
             {Name=header Row=toprow Column=leftcol,rightcol},
             {Name=footer Row=bottomrow Column=leftcol,rightcol}">

      <Image Grid.Area="imageArea"/>

      <TextBlock Grid.Area="Header"/>

      <Button Grid.Row="bottomrow" Grid.Column="rightcol"/>
</Grid>

Auto-flow Layout w/ Auto-generated Rows (or Columns)

<Grid ColumnDefinitions="240, 1*"
      ColumnSpacing="18"
      AutoFlow="Row"
      AutoRowDefinitions="{MinHeight=80 Height=Auto}">
  <Grid.Resources>
      <Style TargetType="TextBlock">
          <Setter Property="HorizontalAlignment" Value="Right"/>
      </Style>
  </Grid.Resources>

  <TextBlock Text="Id"/>
  <TextBox x:Name="IdField"/>

  <TextBlock Text="Name"/>
  <TextBox x:Name="NameField"/>

  <TextBlock Text="Address"/>
  <TextBox x:Name="AddressField"/>

  <!-- Inserting a new label + field or re-ordering them doesn't require 
       updating all the Column/Row assignments -->

</Grid>

The AutoFlow property determines how elements that aren't explicitly assigned to an area / row / column will be placed. The default is 'None'. A value of 'Row' causes the layout to attempt to sequentially fill the columns of a row before moving to the next row. It can leave gaps by not considering if elements seen later could have fit on earlier rows.
A value of 'RowDense', however, would attempt to fill in the earlier gaps with elements seen later. RowDense can affect the visual ordering and could adversely impact accessibility. Similar behavior applies to values of Column and ColumnDense.

Detailed Feature Design

Open Questions

Would a Grid with these capabilities (i.e. named areas and autoflow + autogenerated rows/columns) simplify the way that you currently use Grid? For what scenario?
Which of the proposed enhancements would you find most useful?

  • compact syntax for defining rows/columns,
  • support for defining and using named columns and rows,
  • autoflow and auto-generated rows/columns)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions