Контейнер Grid располагает вложенные элементы в виде таблицы. Для образования таблицы клас Grid предоставляет два свойства:
RowDefinitions: коллекция строк. Каждая строка представляет объект RowDefinition
ColumnDefinitions: коллекция столбцов. Каждый столбец представляет объект ColumnDefinition
Например, в следующем коде определяется грид с двумя строками и тремя столбцами:
Grid grid = new Grid { RowDefinitions = { new RowDefinition(), new RowDefinition() }, ColumnDefinitions = { new ColumnDefinition(), new ColumnDefinition(), new ColumnDefinition() } };
Определение в XAML
<Grid> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> </Grid>
Определив строки и столбцы грида, мы можем добавить визуальный элемент в определенную клетку грида. Для этого у объекта Grid применяется метод Add():
void Add(IView view, int column = 0, int row = 0);
Первый параметр - добавляемый элемент, второй - номер столбца (нумерация с нуля) и третий - номер строки.
Пример простейшего грида из двух строк и трех столбцов:
namespace HelloApp { class StartPage : ContentPage { public StartPage() { Grid grid = new Grid { RowDefinitions = { new RowDefinition(), new RowDefinition() }, ColumnDefinitions = { new ColumnDefinition(), new ColumnDefinition(), new ColumnDefinition() } }; grid.Add(new BoxView { Color = Colors.Red }, 0, 0); grid.Add(new BoxView { Color = Colors.Blue }, 0, 1); grid.Add(new BoxView { Color = Colors.Teal }, 1, 0); grid.Add(new BoxView { Color = Colors.Green }, 1, 1); grid.Add(new BoxView { Color = Colors.Olive }, 2, 0); grid.Add(new BoxView { Color = Colors.Pink }, 2, 1); Content = grid; } } }
Здесь в каждую клетку грида добавляется элемент BoxView, который представляет закрашиваемую прямоугольную область. В итоге мы получим примерно следующую картину:
Аналогичный пример в xaml:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="HelloApp.MainPage"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <BoxView Color="Red" Grid.Column="0" Grid.Row="0" /> <BoxView Color="Blue" Grid.Column="0" Grid.Row="1" /> <BoxView Color="Teal" Grid.Column="1" Grid.Row="0" /> <BoxView Color="Green" Grid.Column="1" Grid.Row="1" /> <BoxView Color="Olive" Grid.Column="2" Grid.Row="0" /> <BoxView Color="Pink" Grid.Column="2" Grid.Row="1" /> </Grid> </ContentPage>
В XAML для установки положения элемента у него применяются прикрепляемые свойства - Grid.Column (устанавливает номер столбца) и Grid.Row (для установки номера строки).
В примере выше размеры ячеек грида и соответственно вложенных элементов BoxView устанавливались автоматически. Но также можно установить размеры явным образом. У объекта RowDefinition помощью свойства Height можно установить высоту строки. Аналогично у объекта ColumnDefinition свойство Width позволяет установить ширину столбца. Однако оба эти свойства принимают не просто какое-то числовое значение, а объект типа GridLength.
Для установки размеров GridLength определяет два конструктора:
public GridLength(); public GridLength(double value); public GridLength(double value, GridUnitType type);
Параметр value представляет собственно числовое значение. А параметр type указывает, как это значение будет интерпретироваться.
Используем вторую версию конструктора, которая задает только числовые значения:
namespace HelloApp { class StartPage : ContentPage { public StartPage() { Grid grid = new Grid { RowDefinitions = { new RowDefinition{ Height=new GridLength(120) }, new RowDefinition() }, ColumnDefinitions = { new ColumnDefinition{Width = new GridLength(100)}, new ColumnDefinition(), new ColumnDefinition{Width = new GridLength(100)}, } }; grid.Add(new BoxView { Color = Colors.Red }, 0, 0); grid.Add(new BoxView { Color = Colors.Blue }, 0, 1); grid.Add(new BoxView { Color = Colors.Teal }, 1, 0); grid.Add(new BoxView { Color = Colors.Green }, 1, 1); grid.Add(new BoxView { Color = Colors.Olive }, 2, 0); grid.Add(new BoxView { Color = Colors.Pink }, 2, 1); Content = grid; } } }
Здесь первая строка имеет высоту 120 единиц. Для второй строки высота не задана, поэтому она получает автоматическую высоту - занимает все оставшееся пространство.
Аналогично для первого и третьего столбца задана ширина в 100 единиц. Для второго столбца ширина не задана, поэтому он занимает всю оставшуюся область.
Аналогичный пример в XAML:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="HelloApp.MainPage"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="100" /> <ColumnDefinition /> <ColumnDefinition Width="100" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="120" /> <RowDefinition /> </Grid.RowDefinitions> <BoxView Color="Red" Grid.Column="0" Grid.Row="0" /> <BoxView Color="Blue" Grid.Column="0" Grid.Row="1" /> <BoxView Color="Teal" Grid.Column="1" Grid.Row="0" /> <BoxView Color="Green" Grid.Column="1" Grid.Row="1" /> <BoxView Color="Olive" Grid.Column="2" Grid.Row="0" /> <BoxView Color="Pink" Grid.Column="2" Grid.Row="1" /> </Grid> </ContentPage>
Фреймворк MAUI также позволяет задать пропорциональные размеры:
namespace HelloApp { class StartPage : ContentPage { public StartPage() { Grid grid = new Grid { RowDefinitions = { new RowDefinition{ Height=new GridLength(1, GridUnitType.Star) }, new RowDefinition{ Height=new GridLength(2, GridUnitType.Star) } }, ColumnDefinitions = { new ColumnDefinition{Width = new GridLength(1, GridUnitType.Star)}, new ColumnDefinition{Width = new GridLength(2, GridUnitType.Star)}, new ColumnDefinition{Width = new GridLength(1, GridUnitType.Star)} } }; grid.Add(new BoxView { Color = Colors.Red }, 0, 0); grid.Add(new BoxView { Color = Colors.Blue }, 0, 1); grid.Add(new BoxView { Color = Colors.Teal }, 1, 0); grid.Add(new BoxView { Color = Colors.Green }, 1, 1); grid.Add(new BoxView { Color = Colors.Olive }, 2, 0); grid.Add(new BoxView { Color = Colors.Pink }, 2, 1); Content = grid; } } }
Для установки пропорциональных размеров в конструктор GridLength в качестве второго параметра передается значение GridUnitType.Star
. Например, возьмем высоту первой строки:
new RowDefinition{ Height=new GridLength(1, GridUnitType.Star) }
Число 1 здесь указывает на то, что данная строка будет занимать одну долю от всей высоты контейнера.
Для второй строки это значение равно 2:
new RowDefinition{ Height=new GridLength(2, GridUnitType.Star) }
Таким образом, сумма весов всех строк равна 1 + 2 = 3. Поэтому первая строка получит 1/3 высоты контейнера, а вторая строка - 2/3 высоты контейнера.
Аналогично вычисляется ширина столбцов. Первый столбец имеет ширину 1, второй столбец - 2 и третий столбец - 1. В итоге сумма весов всех столбцов равен 1 + 2 + 1 = 4. Поэтому первый и третий столбцы получат 1/4 ширины контейнера, а второй столбец - 2/4 (то есть половину) ширины контейнера.
Аналогичный пример в xaml:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="HelloApp.MainPage"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="2*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="2*" /> </Grid.RowDefinitions> <BoxView Color="Red" Grid.Column="0" Grid.Row="0" /> <BoxView Color="Blue" Grid.Column="0" Grid.Row="1" /> <BoxView Color="Teal" Grid.Column="1" Grid.Row="0" /> <BoxView Color="Green" Grid.Column="1" Grid.Row="1" /> <BoxView Color="Olive" Grid.Column="2" Grid.Row="0" /> <BoxView Color="Pink" Grid.Column="2" Grid.Row="1" /> </Grid> </ContentPage>
При необходимости можно также сочетать различные типы размеров.
Класс Grid определяет два специальных свойства для создания отступов:
ColumnSpacing: определяет пространство между столбцами
RowSpacing: определяет пространство между строками
Например:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="HelloApp.MainPage"> <Grid ColumnSpacing="5" RowSpacing="8"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="2*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="2*" /> </Grid.RowDefinitions> <BoxView Color="Red" Grid.Column="0" Grid.Row="0" /> <BoxView Color="Blue" Grid.Column="0" Grid.Row="1" /> <BoxView Color="Teal" Grid.Column="1" Grid.Row="0" /> <BoxView Color="Green" Grid.Column="1" Grid.Row="1" /> <BoxView Color="Olive" Grid.Column="2" Grid.Row="0" /> <BoxView Color="Pink" Grid.Column="2" Grid.Row="1" /> </Grid> </ContentPage>
Или в коде C#:
var grid = new Grid { ColumnSpacing = 5, RowSpacing = 8, RowDefinitions = { new RowDefinition{ Height=new GridLength(1, GridUnitType.Star) }, new RowDefinition{ Height=new GridLength(2, GridUnitType.Star) } }, ColumnDefinitions = { new ColumnDefinition{Width = new GridLength(1, GridUnitType.Star)}, new ColumnDefinition{Width = new GridLength(2, GridUnitType.Star)}, new ColumnDefinition{Width = new GridLength(1, GridUnitType.Star)} } };
С помощью свойства ColumnSpan можно объединить несколько столбцов, а с помощью свойства RowSpan - объединить строки:
namespace HelloApp { class StartPage : ContentPage { public StartPage() { Grid grid = new Grid { RowDefinitions = { new RowDefinition(), new RowDefinition() }, ColumnDefinitions = { new ColumnDefinition(), new ColumnDefinition() } }; BoxView blueBox = new BoxView { Color = Colors.LightBlue }; BoxView greenBox = new BoxView { Color = Colors.Teal }; BoxView pinkBox = new BoxView { Color = Colors.LightPink }; grid.Add(blueBox, 0, 0); grid.Add(greenBox, 1, 0); grid.Add(pinkBox, 0, 1); Grid.SetColumnSpan(pinkBox, 2); // растягиваем на два столбца Content = grid; } } }
Аналог в XAML:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="HelloApp.MainPage"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <BoxView Color="LightBlue" Grid.Column="0" Grid.Row="0" /> <BoxView Color="Teal" Grid.Column="1" Grid.Row="0" /> <BoxView Color="LightPink" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2" /> </Grid> </ContentPage>