Довольно часто, при работе над приложением .NET MAUI нам требуется сделать привязку не к отдельному объекту и его свойству, а сразу к списку объектов. Например, чтобы вывести на экран список пользователей, проектов, задач и так далее. На данный момент мы уже знаем про такой элемент управления, как Picker
. В этой части мы рассмотрим то, как можно заполнить этот элемент списком объектов, а также раздеремся с шаблонами данных на примере еще одного элемента — CollectionView
.
Заполнение Picker списком объектов
Теперь, когда мы изучили основы привязки данных в .NET MAUI, можно рассмотреть ещё один вариант работы с элементом Picker
и заполнить список его элементов, используя объекты своего класса. Для примера, воспользуемся классом Project
, который мы рассматривали в предыдущей части. Вот как выглядит наш класс:
public class Project : INotifyPropertyChanged { string name = ""; bool isActive = false; double cost = 0; public string Name { get => name; set { if (name != value) { name = value; OnPropertyChanged(); } } } public bool IsActive { get => isActive; set { if (isActive != value) { isActive = value; OnPropertyChanged(); } } } public double Cost { get => cost; set { if (cost != value) { cost = value; OnPropertyChanged(); } } } public event PropertyChangedEventHandler? PropertyChanged; public void OnPropertyChanged([CallerMemberName] string prop = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop)); } }
Используем объекты этого класса для заполнения списка. Добавим на страницу MainPage
следующий ресурс:
<ContentPage.Resources> <ResourceDictionary> <x:Array x:Key="Projects" Type="{x:Type local:Project}"> <local:Project Name="Проект №1" IsActive="True" Cost="120"/> <local:Project Name="Проект №2" IsActive="True" Cost="130"/> <local:Project Name="Проект №3" IsActive="True" Cost="140"/> <local:Project Name="Проект №4" IsActive="True" Cost="150"/> <local:Project Name="Проект №5" IsActive="True" Cost="160"/> </x:Array> </ResourceDictionary> </ContentPage.Resources>
Зная основы привязки, мы можем легко привязать этот массив объектов к списку Picker.ItemSource
, например так:
<VerticalStackLayout BindingContext="{StaticResource Projects}"> <Picker ItemsSource="{StaticResource Projects}" ItemDisplayBinding="{Binding Path=Name}"/> </VerticalStackLayout>
Здесь мы передаем в ItemSource
массив и дополнительно привязываем свойство Picker.ItemDisplayBinding
к свойству Name
класса Project
. Теперь наш список будет таким:
Более того, мы можем ещё сократить этот код. Так как контекст привязки определен в родительском контейнере и это, по сути, всё тот же массив элементов, то мы можем привязаться к нему используя расширение разметки Binding
вот так:
<VerticalStackLayout BindingContext="{StaticResource Projects}"> <Picker ItemsSource="{Binding}" ItemDisplayBinding="{Binding Path=Name}"/> </VerticalStackLayout>
Результат работы приложение будет точно таким же, как и на рисунке выше.
Шаблоны данных (DataTemplate)
Рассмотрим ещё один пример работы с коллекциями объектов на примере пока ещё не изученного нами элемента управления — CollectionView
. Элемент CollectionView
предназначен для отображения списка однотипных данных. Этот элемент имеет достаточно гибкую систему различных настроек и, как следствие, содержит множество свойств для работы. Однако мы сосредоточимся на главном и разберемся с тем как заполнить CollectionView
коллекцией объектов своего класса. Для работы нам потребуется всего два свойства CollectionView
:
Свойство | Тип | Описание |
Items |
IEnumerable |
Коллекция объектов, которые необходимо отобразить в списке |
ItemTemplate |
DataTemplate |
Шаблон данных |
Элемент CollectionView предназначен для отображения данных любых объектов и изначально, если передать в свойстве ItemSource
коллекцию объектов, то CollectionView
будет пытаться отобразить эти данные, используя метод ToString()
класса. Например, вернемся к нашему приложению и добавим в него новый элемент управления:
<VerticalStackLayout BindingContext="{StaticResource Projects}"> <Picker ItemsSource="{Binding}" ItemDisplayBinding="{Binding Path=Name}"/> <CollectionView ItemsSource="{Binding}"/> </VerticalStackLayout>
В результате, мы увидим вот такой список объектов:
Можно было бы переопределить в нашем классе метод ToString()
и выводить в список необходимые нам строки, но это не самый лучший вариант так как нам может потребоваться использовать свойства объектов в различных вариациях в разных элементах управления. Здесь нам и потребуется второе свойство — ItemTemplate
Перепишем код элемента следующим образом:
<CollectionView ItemsSource="{Binding}"> <CollectionView.ItemTemplate> <DataTemplate x:DataType="{x:Type local:Project}"> <Border Background="LightGray" Padding="5"> <VerticalStackLayout> <Label Text="{Binding Name}"/> <CheckBox IsChecked="{Binding IsActive}"/> <Label Text="{Binding Cost}"/> </VerticalStackLayout> </Border> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView>
В свойстве ItemTemplate
мы указываем шаблон данных, то есть то, как наш объект должен отображаться в списке. Свойство x:DataType
у DataTemplate
указывает объект какого типа будет участвовать при формировании шаблона:
<DataTemplate x:DataType="{x:Type local:Project}">
Далее, внутри DataTemplate
мы указываем как визуально будет отображаться объект — здесь мы можем использовать любые элементы управления, применять к ним стили, задействовать другие ресурсы и так далее. Стоит обратить внимание на то как производится привязка к свойствам объекта. Так как тип объекта известен, а коллекция таких объектов уже привязана к свойству ItemSource
, то мы используем при привязке только имена свойств:
<Label Text="{Binding Name}"/> <CheckBox IsChecked="{Binding IsActive}"/> <Label Text="{Binding Cost}"/>
В итоге, в приложении будет сформирован вот такой список проектов:
Итого
Используя привязку в .NET MAUI мы можем привязывать к элементам управления коллекции объектов. Для отображения данных сложных объектов удобно пользоваться шаблонами данных, определяя свойство ItemTemplate
типа DataTemplate
у элемента управления.