This document specifies the current behavior and design of the Grid control as implemented.
For end-user usage and examples, see Grid.
Fixed(n), Auto, Star(weight), FlexStar(weight).Min/Max constraints.Cells insertion order).GridRowDefinitions : BindableList<RowDefinition>ColumnDefinitions : BindableList<ColumnDefinition>Cells : BindableList<GridCell>Padding : ThicknessRowGap : intColumnGap : intAutoGrowRows : bool (default true)AutoGrowColumns : bool (default true)GridCellGridCell is a ContentVisual that carries placement information.
Row : int (clamped to >= 0)Column : int (clamped to >= 0)RowSpan : int (clamped to >= 1)ColumnSpan : int (clamped to >= 1)Content : Visual? (inherited from ContentVisual)HorizontalAlignment = Align.Stretch, VerticalAlignment = Align.Stretch.AutoGrowRows = true, AutoGrowColumns = true.RowDefinitions or ColumnDefinitions are empty, tracks default to Star(1).src/XenoAtom.Terminal.UI/Controls/Grid.cssrc/XenoAtom.Terminal.UI/Controls/GridCell.cssrc/XenoAtom.Terminal.UI/Layout/FlexAllocator.cssrc/XenoAtom.Terminal.UI.Tests/GridLayoutTests.cssamples/ControlsDemo/Demos/GridDemo.csRowDefinition.Height and ColumnDefinition.Width use GridLength with:
Fixed(n): track size is exactly n (after min/max clamping).Auto: track size is derived from the maximum child size in that track (span == 1), with no extra growth.Star(weight): weighted remaining-space sizing. On bounded axes it divides the available remaining space by weight and then enforces min/max constraints.FlexStar(weight): content-aware weighted sizing. It tracks intrinsic child size first, then participates in growth when extra space is available.ColumnDefinition.MinWidth / MaxWidthRowDefinition.MinHeight / MaxHeightMin is always respected; Max is enforced when finite.
The effective row/column counts are derived from:
max(1, RowDefinitions.Count) and max(1, ColumnDefinitions.Count)(Row + RowSpan) / (Column + ColumnSpan) requested by any cellIf AutoGrowRows is false, the grid uses only the definition count (minimum 1) even if cells address rows beyond it.
The same applies to AutoGrowColumns.
If definitions exist but are fewer than the effective count, the missing tracks are implicitly Star(1).
Grid is a layout-only container:
RowGap and ColumnGap are clamped to >= 0.(rows - 1) * RowGap and (cols - 1) * ColumnGap (when there are at least 2 tracks).Grid.Measure runs a two-pass measure to support width-dependent heights (wrapping):
Only non-fixed tracks are influenced by cell measurement hints, and only for cells with span == 1.
For each row/column, the grid constructs arrays:
min[], natural[], max[]grow[], shrink[]The arrays are initialized from the track definitions:
Fixed: min/natural/max are set to the fixed size (clamped to min/max); grow/shrink are 0.Auto / Star / FlexStar:
min and natural are the track min (MinWidth/MinHeight)max is MaxWidth/MaxHeight (or infinite), normalized to be at least mingrow is 0 for Auto, and >= 1 for Star/FlexStar (from the weight with a default of 1)shrink is 1Then, after measuring cells:
ColumnSpan == 1, the column's min is updated to the max of the cell min hint.RowSpan == 1, the row's min is updated to the max of the cell min hint.Auto and FlexStar also update natural from child natural hints.Star updates natural from child natural hints only when the measured axis is unbounded; on bounded axes the weighted allocation uses a zero-width baseline for Star tracks so child natural widths/heights and track minimums do not bias the ratio unless a min/max constraint actually binds.The grid then normalizes tracks so natural is clamped to [min..max] when max is finite.
When the width is bounded and at least one column is Star, the grid reports its own natural width from the bounded column
allocation result rather than from Sum(colNat). This keeps the Star ratio content-agnostic while still giving start-aligned
parents a meaningful desired width.
During arrange, bounded Star axes use a star-aware allocation step before final min enforcement; other cases use FlexAllocator.Allocate(...):
min according to shrink weights.After allocation, the grid computes offsets using padding + gaps, then arranges each cell into its spanned rect.
When measuring with an unbounded width (max width is infinite), the grid treats Star columns as intrinsic:
availableForColumns = Sum(colNat) instead of infinite.This makes the grid report a meaningful desired width in unbounded measure scenarios (see GridLayoutTests.Unbounded_Measure_Treats_Star_Columns_As_Intrinsic).
FlexStar tracks are also intrinsic on unbounded axes, because they always track child natural size.
Spans affect placement (the arranged rect size), but span > 1 does not contribute to track sizing:
min/natural of the spanned tracks during measure.This is a deliberate simplification in the current implementation and is a key limitation to keep in mind when authoring complex grids.
There is no GridStyle. Styling is achieved by wrapping the grid or individual cells (e.g., Border, Group, Rule), and by styling the cell content visuals.
None. Input routing and focus are handled by child visuals.
GridLayoutTests covers:
GridDemo shows typical form-like layouts using the fluent .Rows(...), .Columns(...), and .Cell(...) helpers.