Элемент CollectionView по умолчанию располагает элементы вертикально. Однако вообще у нас есть 4 варианта расположения элементов:
Вертикальный список — список из одного столбца
Горизонтальный список — список из одной строки, который растет горизонтально по мере добавления новых элементов.
Вертикальный грид — грид из нескольких столбцов, который растет вертикально по мере добавления новых элементов.
Горизонтальный грид — грид из нескольких строкк, который увеличивается по горизонтали по мере добавления новых элементов.
С помощью свойства ItemsLayout можно настроить расположение. Это свойство представляет объект IItemsLayout. Обычно это объект класса, производного от ItemsLayout
Этот класс определяет свойство Orientation, которое представляет перечисление ItemsLayoutOrientation
. В этом перечислении определены две константы:
Vertical
: элементы располагаются вертикально
Horizontal
: элементы располагаются горизонтально
По умолчанию .NET MAUI предоставляет две реализации класса ItemsLayout - LinearItemsLayout (для создания списка) и GridItemsLayout (для создания грида)
Для создания списков применяется класс LinearItemsLayout. Он определяет статические поля Vertical
и Horizontal
для создания вертикальных или горизонтальных списков соответственно.
В качестве альтернативы можно создать объект LinearItemsLayout и передать в его конструктор одну из двух констант перечисления ItemsLayoutOrientation
.
// вертикальный список LinearItemsLayout layout = new LinearItemsLayout(ItemsLayoutOrientation.Vertical); // горизонтальный список layout = new LinearItemsLayout(ItemsLayoutOrientation.Horizontal);
Кроме того, класс LinearItemsLayout
определяет свойство ItemSpacing
типа double
, которое представояет
пустое пространство вокруг каждого элемента. Значение этого свойства по умолчанию равно 0, и его значение всегда должно быть больше или равно 0.
По умолчанию для CollectionView определяется вертикальный список. И в принципе мы можем также явным образом задать вертикальное расположение. В коде C#:
collectionView.ItemsLayout = LinearItemsLayout.Vertical; // или так collectionView.ItemsLayout = new LinearItemsLayout(ItemsLayoutOrientation.Vertical);
В коде xaml:
<CollectionView ItemsLayout="VerticalList"> ... </CollectionView> <!-- или так --> <CollectionView> <CollectionView.ItemsLayout> <LinearItemsLayout Orientation="Vertical" /> </CollectionView.ItemsLayout> ... </CollectionView>
Горизонтальный список делается аналогично. В коде C#:
collectionView.ItemsLayout = LinearItemsLayout.Horizontal; // или так collectionView.ItemsLayout = new LinearItemsLayout(ItemsLayoutOrientation.Horizontal);
В коде xaml:
<CollectionView ItemsLayout="HorizontalList"> ... </CollectionView> <!-- или так --> <CollectionView> <CollectionView.ItemsLayout> <LinearItemsLayout Orientation="Horizontal" /> </CollectionView.ItemsLayout> ... </CollectionView>
Рассмотрим на примере. Допустим, данные представлены классом Person:
public class Person { public string Name { get; set; } = ""; public int Age { get; set; } public string Company { get; set; } = ""; }
Класс Person определяет три свойства: Name, Age и Company для хранения имени, возраста и компании пользователя соответственно.
Определим в коде C# страницу, которая выводит список подобных объектов:
namespace HelloApp; class StartPage : ContentPage { public StartPage() { CollectionView collectionView = new CollectionView(); collectionView.ItemsLayout = LinearItemsLayout.Horizontal; // определяем источник данных collectionView.ItemsSource = new List<Person> { new Person { Name="Tom", Age=38, Company ="Microsoft" }, new Person { Name="Sam", Age=25, Company ="Google" }, new Person { Name="Bob", Age=42, Company ="JetBrains" }, new Person { Name="Alice", Age=33, Company ="Microsoft" }, new Person { Name="Kate", Age=29, Company ="Google" }, new Person { Name="Amelia", Age=35, Company ="JetBrains" }, }; // определяем шаблон данных collectionView.ItemTemplate = new DataTemplate(() => { var nameLabel = new Label { FontSize = 20, TextColor = Color.FromArgb("#006064"), Margin = 10 }; nameLabel.SetBinding(Label.TextProperty, "Name"); var ageLabel = new Label(); ageLabel.SetBinding(Label.TextProperty, new Binding { Path = "Age", StringFormat = "Возраст: {0}" }); var companyLabel = new Label(); companyLabel.SetBinding(Label.TextProperty, "Company"); return new StackLayout { Children = { nameLabel, ageLabel, companyLabel }, Margin = 20 }; }); Content = collectionView ; } }
Здесь шаблон элементов представлен объектом StackLayout, в котором в 3-х метках выводятся значения текущего объекта Person.
С помощью свойства ItemsLayout
задаем горизонтальное направление элементов:
collectionView.ItemsLayout = LinearItemsLayout.Horizontal;
В итоге элементы будут располагаться в горизонтальный ряд:
Аналогичный код в 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" xmlns:local="clr-namespace:HelloApp"> <CollectionView ItemsLayout="HorizontalList"> <CollectionView.ItemsSource> <x:Array Type="{x:Type local:Person}"> <local:Person Name="Tom" Age="38" Company="Microsoft"/> <local:Person Name="Sam" Age="25" Company="Google"/> <local:Person Name="Bob" Age="42" Company="JetBrains"/> <local:Person Name="Alice" Age="33" Company="Microsoft"/> <local:Person Name="Kate" Age="29" Company="Google"/> <local:Person Name="Amelia" Age="35" Company="JetBrains" /> </x:Array> </CollectionView.ItemsSource> <CollectionView.ItemTemplate> <DataTemplate> <StackLayout Margin="10"> <Label Text="{Binding Name}" FontSize = "20" TextColor = "#006064" Margin="10" /> <Label Text="{Binding Age, StringFormat='Возраст: {0}'}" /> <Label Text="{Binding Company}" /> </StackLayout> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> </ContentPage>
С помощью свойства ItemSpacing можно задать отступы между элементами. Например, в xaml:
<CollectionView> <CollectionView.ItemsLayout> <LinearItemsLayout Orientation="Horizontal" ItemSpacing="20" /> </CollectionView.ItemsLayout> ......... </CollectionView>
Или в коде C#
CollectionView collectionView = new CollectionView(); collectionView.ItemsLayout = new LinearItemsLayout(ItemsLayoutOrientation.Horizontal){ ItemSpacing = 10 };
Для создания гридов предназначен класс GridItemsLayout, который наследуется от класса ItemsLayout и определяет следующие свойства:
VerticalItemSpacing: значение типа double
, которое представляет пустое пространство вокруг каждого элемента сверху и снизу.
По умолчанию равно 0, и это значение всегда должно быть больше или равно 0.
HorizontalItemSpacing: значение типа double
, которое представляет пустое пространство вокруг каждого элемента справа и слева.
По умолчанию равно 0, и это значение всегда должно быть больше или равно 0.
Span: значение типа int
, которое представляет количество столбцов или строк, отображаемых в гриде.
По умолчанию равно 1 и всегда должно быть больше или равно 1.
Эти свойства представляют BindableProperty, поэтому их можно использовать как цель привязки данных.
Для создания грида необходимо присвоить свойству ItemsLayout
объекта CollectionView
объект GridItemsLayout c указанием ориентации
и количеством строк/столбцов. Например, в коде C#:
CollectionView collectionView = new CollectionView(); // 2 столбца collectionView.ItemsLayout = new GridItemsLayout(ItemsLayoutOrientation.Vertical) { Span = 2 }; // 2 строки collectionView.ItemsLayout = new GridItemsLayout(ItemsLayoutOrientation.Horizontal) { Span = 2 };
В коде xaml можно использовать краткую форму
<CollectionView ItemsLayout="VerticalGrid, 2">
Сначала указывается ориентация - "VerticalGrid" или "HorizontalGrid", а затем количество строк/столбцов
Также можно использовать полную форму:
<CollectionView> <CollectionView.ItemsLayout> <GridItemsLayout Orientation="Vertical" Span="2" /> </CollectionView.ItemsLayout> ........... </CollectionView>
Вертикальный грид представляет расположение элементов в несколько колонок/столбцов. Например, определим в C# вертикальный грид из двух колонок:
namespace HelloApp; class StartPage : ContentPage { public StartPage() { CollectionView collectionView = new CollectionView { VerticalOptions = LayoutOptions.Start}; // 2 столбца collectionView.ItemsLayout = new GridItemsLayout(ItemsLayoutOrientation.Vertical) { Span = 2 }; // определяем источник данных collectionView.ItemsSource = new List<Person> { new Person { Name="Tom", Age=38, Company ="Microsoft" }, new Person { Name="Sam", Age=25, Company ="Google" }, new Person { Name="Bob", Age=42, Company ="JetBrains" }, new Person { Name="Alice", Age=33, Company ="Microsoft" }, new Person { Name="Kate", Age=29, Company ="Google" }, new Person { Name="Amelia", Age=35, Company ="JetBrains" }, }; // определяем шаблон данных collectionView.ItemTemplate = new DataTemplate(() => { var nameLabel = new Label { FontSize = 20, TextColor = Color.FromArgb("#006064"), Margin = 10 }; nameLabel.SetBinding(Label.TextProperty, "Name"); var ageLabel = new Label(); ageLabel.SetBinding(Label.TextProperty, new Binding { Path = "Age", StringFormat = "Возраст: {0}" }); var companyLabel = new Label(); companyLabel.SetBinding(Label.TextProperty, "Company"); return new StackLayout { Children = { nameLabel, ageLabel, companyLabel }, Margin = 20 }; }); Content = collectionView ; } }
Аналогичный код в 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" xmlns:local="clr-namespace:HelloApp"> <CollectionView ItemsLayout="VerticalGrid, 2"> <CollectionView.ItemsSource> <x:Array Type="{x:Type local:Person}"> <local:Person Name="Tom" Age="38" Company="Microsoft"/> <local:Person Name="Sam" Age="25" Company="Google"/> <local:Person Name="Bob" Age="42" Company="JetBrains"/> <local:Person Name="Alice" Age="33" Company="Microsoft"/> <local:Person Name="Kate" Age="29" Company="Google"/> <local:Person Name="Amelia" Age="35" Company="JetBrains" /> </x:Array> </CollectionView.ItemsSource> <CollectionView.ItemTemplate> <DataTemplate> <StackLayout Margin="8"> <Label Text="{Binding Name}" FontSize = "20" TextColor = "#006064" Margin="10" /> <Label Text="{Binding Age, StringFormat='Возраст: {0}'}" /> <Label Text="{Binding Company}" /> </StackLayout> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> </ContentPage>
Определим горизонтальный грид из 3 строк в коде C#:
namespace HelloApp; class StartPage : ContentPage { public StartPage() { CollectionView collectionView = new CollectionView { VerticalOptions = LayoutOptions.Start}; // три строки collectionView.ItemsLayout = new GridItemsLayout(ItemsLayoutOrientation.Horizontal) { Span = 3 }; // определяем источник данных collectionView.ItemsSource = new List<Person> { new Person { Name="Tom", Age=38, Company ="Microsoft" }, new Person { Name="Sam", Age=25, Company ="Google" }, new Person { Name="Bob", Age=42, Company ="JetBrains" }, new Person { Name="Alice", Age=33, Company ="Microsoft" }, new Person { Name="Kate", Age=29, Company ="Google" }, new Person { Name="Amelia", Age=35, Company ="JetBrains" }, new Person { Name="Mike", Age=36, Company ="Google" }, }; // определяем шаблон данных collectionView.ItemTemplate = new DataTemplate(() => { var nameLabel = new Label { FontSize = 20, TextColor = Color.FromArgb("#006064")}; nameLabel.SetBinding(Label.TextProperty, "Name"); var ageLabel = new Label(); ageLabel.SetBinding(Label.TextProperty, new Binding { Path = "Age", StringFormat = "Возраст: {0}" }); var companyLabel = new Label(); companyLabel.SetBinding(Label.TextProperty, "Company"); return new StackLayout { Children = { nameLabel, ageLabel, companyLabel }, Margin = 8, }; }); Content = collectionView ; } }
Аналогичный код в 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" xmlns:local="clr-namespace:HelloApp"> <CollectionView ItemsLayout="HorizontalGrid, 3" VerticalOptions="Start"> <CollectionView.ItemsSource> <x:Array Type="{x:Type local:Person}"> <local:Person Name="Tom" Age="38" Company="Microsoft"/> <local:Person Name="Sam" Age="25" Company="Google"/> <local:Person Name="Bob" Age="42" Company="JetBrains"/> <local:Person Name="Alice" Age="33" Company="Microsoft"/> <local:Person Name="Kate" Age="29" Company="Google"/> <local:Person Name="Amelia" Age="35" Company="JetBrains" /> <local:Person Name="Mike" Age="36" Company="Google"/> </x:Array> </CollectionView.ItemsSource> <CollectionView.ItemTemplate> <DataTemplate> <StackLayout Margin="8"> <Label Text="{Binding Name}" FontSize = "20" TextColor = "#006064"/> <Label Text="{Binding Age, StringFormat='Возраст: {0}'}" /> <Label Text="{Binding Company}" /> </StackLayout> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> </ContentPage>