Контейнер Grid — это еще один контейнер компоновки, доступный нам в .NET MAUI. Отличие от рассмотренных нами ранее контейнеров компоновки, Grid позволяет размещать дочерние компоненты в сетке (таблице). В этой части мы рассмотрим основные моменты по использованию Grid в XAML.
Стоит отметить, что Grid в .NET MAUI — это именно контейнер компоновки и его не следует путать с обычно таблицей, например, наподобие таблиц в HTML.
Работа со строками и столбцами Grid
По умолчанию, Grid уже содержит оду строку и один столбец. Поэтому, если нам достаточно всего одной ячейки сетки, то можно создать вот такой код XAML:
<Grid>
<Button Text="Item 1" Background="Red"></Button>
</Grid>
При этом, опять же, по умолчанию, кнопка растянется на всё доступное пространство в контейнере:
Следует также обратить внимание на то, что каждый следующий дочерний элемент Grid также будет растягиваться на всё пространство и размещаться поверх предыдущего элемента. То есть вот такой код:
<Grid>
<Button Text="Item 1" Background="Red"></Button>
<Button Text="Item 2" Background="Aqua"></Button>
<Button Text="Item 3" Background="Green"></Button>
<Button Text="Item 4" Background="DarkOrange"></Button>
</Grid>
приведет к тому, что последний элемент закроет все предыдущие. То есть мы увидим вот такую страницу приложения:
Чтобы определить строки и столбцы в Grid, мы должны использовать свойства компонента:
RowDefinition— для определения каждой новой строки сеткиColumnDefinition— для определения каждого нового столбца сетки
Например, определим в нашей таблице 4 строки и 4 столбца:
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
</Grid>
Здесь Grid.RowDefinitions — коллекция строк, а Grid.ColumnDefinitions — коллекция столбцов. Теперь мы можем размещать в каждой ячейке сетки какие-либо элементы управления. Делается это с помощью присоединенных свойств, которых мы узнали в предыдущей части, следующим образом:
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Text="Item 1" Background="Red" Grid.Row="0" Grid.Column="0"></Button>
<Button Text="Item 2" Background="Aqua" Grid.Row="1" Grid.Column="1"></Button>
<Button Text="Item 3" Background="Green" Grid.Row="2" Grid.Column="2"></Button>
<Button Text="Item 4" Background="DarkOrange" Grid.Row="3" Grid.Column="3"></Button>
</Grid>
Здесь присоединенное свойство Grid.Row определяет порядковый номер строки в которой будет расположен дочерний элемента, а Grid.Column — порядковый номер столбца. По приведенному выше коду можно понять, что мы пытаемся разместить кнопки по диагонали, то есть вот так:
Размеры строк и столбцов
В приведенном выше примере мы не указывали никаких размеров для строк и столбцов сетки, поэтому размеры ячеек получились одинаковыми. Такое поведение макета не всегда удобно — бывает необходимо установить, например, столбцу в центре автоматический размер, а столбцам слева и справа — фиксированный. При установлении размеров строк и столбцов Grid следует учитывать, что:
RowDefinition(строка) может содержать размер высоты (Height)ColumnDefinition(столбец) — может содержать только ширину (Width)
Как и в случае с размерами в AbsoluteLayout, мы можем указывать размеры как в абсолютных величинах, так и в единицах пропорции. Абсолютные размеры можно указывать обычным образом, например:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100"></RowDefinition>
<RowDefinition Height="60"></RowDefinition>
<RowDefinition Height="90"></RowDefinition>
<RowDefinition Height="200"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="140"></ColumnDefinition>
<ColumnDefinition Width="150"></ColumnDefinition>
<ColumnDefinition Width="160"></ColumnDefinition>
<ColumnDefinition Width="170"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Text="Item 1" Background="Red" Grid.Row="0" Grid.Column="0"></Button>
<Button Text="Item 2" Background="Aqua" Grid.Row="1" Grid.Column="1"></Button>
<Button Text="Item 3" Background="Green" Grid.Row="2" Grid.Column="2"></Button>
<Button Text="Item 4" Background="DarkOrange" Grid.Row="3" Grid.Column="3"></Button>
</Grid>
Здесь мы задали абсолютные значения для ширины столбцов и высоты строк, поэтому на экране мы увидим вот такой неприглядный внешний вид:
Что касается пропорциональных размеров, то здесь все обстоит немного сложнее. Рассмотрим вот такой пример:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"></RowDefinition>
<RowDefinition Height="4*"></RowDefinition>
<RowDefinition Height="1*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="4*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Text="Item 1" Background="Red" Grid.Row="0" Grid.Column="0"></Button>
<Button Text="Item 2" Background="Aqua" Grid.Row="1" Grid.Column="1"></Button>
<Button Text="Item 3" Background="Green" Grid.Row="2" Grid.Column="2"></Button>
</Grid>
Обратите внимание на то, как определены значения размеров — в конце числа стоит символ «звездочка» — *. Этот символ указывает на то, что размер рассчитывается пропорционально. При этом расчёт ведется следующим образом (на примере высот):
- 1 + 4 + 1 = 6 — суммарный размер высот всех строк.
- 1/6 — высота первой строки
- 4/6 (или 2/3) — высота второй строки
- 1/6 — высота третьей строки
Аналогичным образом рассчитывается и ширина столбцов. В итоге, внешний вид нашей сетки с кнопками будет вот таким:
При необходимости, мы можем комбинировать пропорциональные и абсолютные размеры.
Отступы в ячейках сетки
Чтобы сделать отступы в строках и столбцах Grid, используются свойства ColumnSpacing и RowSpacing контейнера Grid. Например,
<Grid RowSpacing="10" ColumnSpacing="10">
<Grid.RowDefinitions>
<RowDefinition Height="1*"></RowDefinition>
<RowDefinition Height="1*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<BoxView Background="Red" Grid.Row="0" Grid.Column="0"></BoxView>
<BoxView Background="Aqua" Grid.Row="0" Grid.Column="1"></BoxView>
<BoxView Background="Green" Grid.Row="1" Grid.Column="1"></BoxView>
<BoxView Background="Yellow" Grid.Row="1" Grid.Column="0"></BoxView>
</Grid>
В результате получим вот такой внешний вид приложения:
Объединение строк и столбцов
Чтобы объединить несколько строк, используется присоединенное свойство Grid.RowSpan, а для объединения столбцов — Grid.ColumnSpan. Например, объединим два столбца в сетке, которая показана на рисунке выше
<Grid RowSpacing="10" ColumnSpacing="10">
<Grid.RowDefinitions>
<RowDefinition Height="1*"></RowDefinition>
<RowDefinition Height="1*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<BoxView Background="Red" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"></BoxView>
<BoxView Background="Green" Grid.Row="1" Grid.Column="1"></BoxView>
<BoxView Background="Yellow" Grid.Row="1" Grid.Column="0"></BoxView>
</Grid>
Итого
Контейнер компоновки Grid используется для размещения содержимого в виде сетки. Размеры ячеек сетки могут задаваться как в абсолютных величинах, так и пропорционально. При необходимости, мы можем объединять строки и столбцы сетки, используя присоединенные свойства.

