question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Simplify Grid definitions, with VerticalGrid and HorizontalGrid

See original GitHub issue

Description

MAUI simplifies stack layouts with VerticalStackLayout and HorizontalStackLayout, allowing for more concise, readable XAML. The proposal here is to do something similar for the other common layout type: Grid, introducing VerticalGrid and HorizontalGrid.

A VerticalGrid is a list of rows, while a HorizontalGrid is a list of columns. They have these advantages over classic Grid:

  • Allows grid definitions without a need to keep track of row/column indices - the numbering is implicit. Rows/columns can be most easily added/removed.
  • Produces XAML markup that more closely matches the actual grid structure - each row/column is a separate indented group, making the grid easier to read and understand.

Public API Changes

Current Syntax

Here’s a typical grid today:

<Grid ColumnDefinitions="0.5*, 0.5*", RowDefinitions="50, 50">
    <Label Text="Column 0, Row 0" />
    <Label Grid.Column="1"
           Text="Column 1, Row 0" />
    <Label Grid.Row="1"
           Text="Column 0, Row 1" />
    <Label Grid.Column="1" Grid.Row="1"
           Text="Column 1, Row 1" />
</Grid>

Proposed Syntax

The same grid as above with the proposed syntax is below:

<VerticalGrid ColumnDefinitions="0.5*, 0.5*">
    <Row Height="50">
        <Label Text="Column 0, Row 0" />
        <Label Text="Column 1, Row 0" />
    </Row>
    <Row Height="50">
        <Label Text="Column 0, Row 1" />
        <Label Text="Column 1, Row 1" />
    </Row>
</VerticalGrid>

Note that there’s no longer a need to specify Grid.Row / Grid.Column, as the row/column index are computed automatically.

Occasionally, a grid is better conceptualized as a list of columns. In that case, it can be expressed with HorizontalGrid:

<HorizontalGrid RowDefinitions="50, 50">
    <Column Width="0.5*">
        <Label Text="Column 0, Row 0" />
        <Label Text="Column 0, Row 1" />
    </Column>
    <Column Width="0.5*">
        <Label Text="Column 1, Row 0" />
        <Label Text="Column 1, Row 1" />
    </Column>
</HorizontalGrid>

Handling Row/Column spans

If a Row element has a child cell that spans adjacent columns, that’s expressed like with a traditional Grid:

<VerticalGrid ColumnDefinitions="0.5*, 0.5, 0.5*">
    <Row Height="50">
        <Label VerticalGrid.ColumnSpan="2" Text="Columns 0 and 1, Row 0" />
        <Label Text="Column 2, Row 0" />
    </Row>
    <Row Height="50">
        <Label Text="Column 0, Row 1" />
        <Label Text="Column 1, Row 1" />
        <Label Text="Column 2, Row 1" />
    </Row>
</VerticalGrid>

If a Row element has a child cell that spans rows below it, it’s expressed as:

<VerticalGrid ColumnDefinitions="0.5*, 0.5, 0.5*">
    <Row Height="50">
        <Label VerticalGrid.RowSpan="2" Text="Column 0, Rows 0 and 1" />
        <Label Text="Column 1, Row 0" />
        <Label Text="Column 2, Row 0" />
    </Row>
    <Row Height="50">
        <SpannedCell/>
        <Label Text="Column 1, Row 1" />
        <Label Text="Column 2, Row 1" />
    </Row>
</VerticalGrid>

Using the SpannedCell dummy element helps makes the grid structure explicit - a cell would have been here, but instead its contents are provided by a row above. In both cases you look at a single Row and see how the children map to columns.

Similarly, an EmptyCell can be used for cases a grid cell is intentionally blank, without spanning:

<VerticalGrid ColumnDefinitions="0.5*, 0.5, 0.5*">
    <Row Height="50">
        <EmptyCell/>
        <Label Text="Column 1, Row 0" />
        <Label Text="Column 2, Row 0" />
    </Row>
    <Row Height="50">
        <Label Text="Column 0, Row 1" />
        <Label Text="Column 1, Row 1" />
        <Label Text="Column 2, Row 1" />
    </Row>
</VerticalGrid>

The rules above mean that tooling can (ideally) enforce that every row/column has the expected number of children, helping minimize mistakes. Row/column indices aren’t used with VerticalGrid/HorizontalGrid.

Prior Art

  • The Flutter Table widget is similar to VerticalGrid. It contains a list of TableRow elements. Flutter doesn’t have an equivalent to HorizontalGrid.
  • HTML tables are a list of tr (table row) elements. HTML developers should find this new Grid syntax intuitive, as it’s the same model.
  • Comet has VGrid and HGrid, which is where I got the idea originally. Comet’s syntax is more concise, as it omits the Row and Column elements, making them implicit based on item index. But I prefer the explicit Row/Column elements, especially for XAML, as it makes the grid structure more obvious and editing less error prone.

Intended Use-Case

Just as VerticalStackLayout / HorizontalStackLayout will likely replace most uses of StackLayout, it’s expected that most uses of Grid will move to using VerticalGrid / HorizontalGrid instead, given its advantages.

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:1
  • Comments:9 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
davidbritchcommented, May 3, 2022

I really like this idea, and the naming. The only bit I’m unsure about is whether it’s a good idea for HorizontalGrid and VerticalGrid to not be capable of everything Grid is capable of.

Something that springs to mind is usage from C#. I get that its intent is to make life easier in XAML, but some people would use these types from C#. In this scenario, what would be the advantage of the new types (VerticalGrid, HorizontalGrid) over using the AddHorizontal and AddVertical methods that were present on a Xamarin.Forms Grid (I don’t think these methods are in .NET MAUI)? These methods added children to a single row or single column Grid. The Grid then expanded its columns/rows as these calls are made, as well as automatically assigning Grid.Column/Row on the children.

0reactions
msftbot[bot]commented, Aug 12, 2022

We’ve moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Feature Proposal: Make Grid Better · Issue #54
It is true that in most cases the Grids only have a few rows and columns, and the simplification of the Definition in...
Read more >
XAML simplify row definitions in Grid
I have a lot of (actually all) <RowDefinition Height="*"/> in my XAML for a single grid. Is there a way to simplify this...
Read more >
Lists and grids | Jetpack Compose
A lazy vertical staggered grid displays its items in a vertically scrollable container that spans across multiple columns and allows individual items to...
Read more >
Understanding the SwiftUI grid layout
Learn to create grids with SwiftUI by developing a reminder app that ... The vertical grid can be divided into multiple columns as...
Read more >
UNDERSTANDING GRID TEMPLATE COLUMN IN CSS ...
CSS grid layout is a two-dimensional system that allows us to position items into rows and columns simultaneously. Image description. Fig 1: A ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found