ListView
Многоплатформенный пользовательский интерфейс приложения .NET (.NET MAUI) ListView отображает прокручиваемый вертикальный список элементов данных, доступных для выбора. При ListView управлении внешним видом списка внешний вид каждого элемента в списке определяется тем DataTemplate , что используется Cell для отображения элементов. .NET MAUI включает типы ячеек для отображения сочетаний текста и изображений, а также можно определить пользовательские ячейки, отображающие любое нужное содержимое. ListView также включает поддержку отображения верхних и нижних колонтитулов, группированных данных, извлечения и обновления элементов контекстного меню.
Класс ListView является производным от ItemsView<Cell>
класса, от которого он наследует следующие свойства:
ItemsSource
IEnumerable
Тип , указывает коллекцию отображаемых элементов и имеет значениеnull
по умолчанию.ItemTemplate
DataTemplateТип , указывает шаблон, применяемый к каждому элементу в коллекции отображаемых элементов.
ListView определяет следующие свойства:
Footer
object
Тип , указывает строку или представление, которое будет отображаться в конце списка.FooterTemplate
, тип DataTemplate, указывает DataTemplate , что используется для форматированияFooter
.GroupHeaderTemplate
DataTemplateТип , определяет DataTemplate используемый для определения внешнего вида заголовка каждой группы. Это свойство является взаимоисключающим с свойствомGroupDisplayBinding
. Поэтому при установке этого свойства задано значениеGroupDisplayBinding
null
.HasUnevenRows
bool
Тип , указывает, могут ли элементы в списке иметь строки разных высот. Значение по умолчанию этого свойства равноfalse
.Header
object
Тип , указывает строку или представление, которое будет отображаться в начале списка.HeaderTemplate
, тип DataTemplate, указывает DataTemplate , что используется для форматированияHeader
.HorizontalScrollBarVisibility
, типScrollBarVisibility
, указывает, когда горизонтальная полоса прокрутки будет видна.IsGroupedEnabled
bool
Тип , указывает, должны ли базовые данные отображаться в группах. Значение по умолчанию этого свойства равноfalse
.IsPullToRefreshEnabled
bool
Тип , указывает, может ли пользователь провести пальцем вниз, чтобы привести ListView к обновлению данных. Значение по умолчанию этого свойства равноfalse
.IsRefreshing
bool
Тип , указывает, обновляется ли в ListView данный момент обновление. Значение по умолчанию этого свойства равноfalse
.RefreshCommand
ICommandТип , представляет команду, которая будет выполняться при активации обновления.RefreshControlColor
ColorТип , определяет цвет визуализации обновления, отображаемой во время обновления.RowHeight
, типint
, определяет высоту каждой строки, когдаHasUnevenRows
этоfalse
.SelectedItem
object
Тип , представляет текущий выбранный элемент в элементе ListView.SelectionMode
ListViewSelectionMode
Тип , указывает, могут ли элементы быть выбраны в ListView или нет. Значение по умолчанию этого свойства равноSingle
.SeparatorColor
ColorТип , определяет цвет панели, разделяющей элементы в списке.SeparatorVisibility
, типаSeparatorVisibility
, определяет, отображаются ли разделители между элементами.VerticalScrollBarVisibility
Тип , указывает, когда вертикальная полоса прокруткиScrollBarVisibility
будет видна.
Все эти свойства поддерживаются BindableProperty объектами, что означает, что они могут быть целевыми объектами привязки данных и стилем.
Кроме того, ListView определяет следующие свойства, которые не поддерживаются BindableProperty объектами:
GroupDisplayBinding
(типBindingBase
) привязка, используемая для отображения заголовка группы. Это свойство является взаимоисключающим с свойствомGroupHeaderTemplate
. Поэтому при установке этого свойства задано значениеGroupHeaderTemplate
null
.GroupShortNameBinding
BindingBase
Тип , привязка для имени, отображаемая в сгруппированных списках переходов.CachingStrategy
, типListViewCachingStrategy
, определяет стратегию повторного использования ячейки ListView. Это свойство доступно только для чтения.
ListView определяет следующие события:
ItemAppearing
, который возникает при добавлении визуального представления элемента в визуальный макет ListViewэлемента. ОбъектItemVisibilityEventArgs
, который сопровождает это событие, определяетItem
иIndex
свойства.ItemDisappearing
, который возникает при удалении визуального представления элемента из визуального макета ListViewэлемента. ОбъектItemVisibilityEventArgs
, который сопровождает это событие, определяетItem
иIndex
свойства.ItemSelected
, который возникает при выборе нового элемента в списке. ОбъектSelectedItemChangedEventArgs
, который сопровождает это событие, определяетSelectedItem
иSelectedItemIndex
свойства.ItemTapped
, который вызывается при нажатии элемента в элементе ListView . ОбъектItemTappedEventArgs
, который сопровождает это событие, определяетGroup
иItem
ItemIndex
свойства.Refreshing
, который возникает при активации ListViewоперации извлечения для обновления.Scrolled
, . ОбъектScrolledEventArgs
, который сопровождает это событие, определяетScrollX
иScrollY
свойства.ScrollToRequested
. ОбъектScrollToRequestedEventArgs
, сопровождающий это событие, определяет Element,Mode
,Position
, иScrollX
ScrollY
ShouldAnimate
свойства.
Заполнение ListView данными
A ListView заполняется данными, задав свойству ItemsSource
любую коллекцию, которая реализует IEnumerable
.
Важно!
ListView Если требуется обновить элементы при добавлении, удалении или изменении в базовой коллекции, базовая коллекция должна быть IEnumerable
коллекцией, которая отправляет уведомления об изменении свойств, напримерObservableCollection
.
ListView можно заполнить данными с помощью привязки данных для привязки его ItemsSource
свойства к IEnumerable
коллекции. В XAML это достигается с расширением Binding
разметки:
<ListView ItemsSource="{Binding Monkeys}" />
Эквивалентный код на C# выглядит так:
ListView listView = new ListView();
listView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
В этом примере ItemsSource
данные свойств привязываются к Monkeys
свойству подключенного представления.
Примечание.
Скомпилированные привязки можно включить для повышения производительности привязки данных в приложениях .NET MAUI. Дополнительные сведения см. в разделе "Скомпилированные привязки".
Дополнительные сведения о привязке данных см. в разделе "Привязка данных".
Определение внешнего вида элемента
Внешний вид каждого элемента в ListView объекте можно определить, задав ItemTemplate
для свойства значение DataTemplate:
<ListView ItemsSource="{Binding Monkeys}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Grid.RowSpan="2"
Source="{Binding ImageUrl}"
Aspect="AspectFill"
HeightRequest="60"
WidthRequest="60" />
<Label Grid.Column="1"
Text="{Binding Name}"
FontAttributes="Bold" />
<Label Grid.Row="1"
Grid.Column="1"
Text="{Binding Location}"
FontAttributes="Italic"
VerticalOptions="End" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Элементы, указанные в DataTemplate определении внешнего вида каждого элемента в списке, и дочерний элемент DataTemplate должен быть Cell объектом. В примере макет в пределах объекта DataTemplate управляется Grid. Image Содержит Grid объект и два Label объекта, которые привязываются ко свойствам Monkey
класса:
public class Monkey
{
public string Name { get; set; }
public string Location { get; set; }
public string Details { get; set; }
public string ImageUrl { get; set; }
}
На следующем снимке экрана показан результат создания шаблонов каждого элемента в списке:
Дополнительные сведения о шаблонах данных см. в разделе "Шаблоны данных".
Cells
Внешний вид каждого элемента в объекте ListViewDataTemplateDataTemplate определяется и должен ссылаться на Cell класс для отображения элементов. Каждая ячейка представляет элемент данных в элементе ListView. .NET MAUI включает следующие встроенные ячейки:
- TextCell, который отображает первичный и вторичный текст на отдельных строках.
- ImageCell, который отображает изображение с первичным и вторичным текстом в отдельных строках.
- SwitchCell, который отображает текст и переключатель, который можно включить или отключить.
- EntryCell, который отображает метку и текст, который можно изменить.
- ViewCell— настраиваемая ячейка, внешний вид которой определяется .View Этот тип ячейки следует использовать, если требуется полностью определить внешний вид каждого элемента в элементе ListView.
Как правило, SwitchCell и EntryCell будет использоваться только в объекте TableView и не будет использоваться в объекте ListView. Дополнительные сведения и SwitchCellEntryCellсведения см. в статье TableView.
Текстовая ячейка
На TextCell отдельных строках отображается основной и вторичный текст. TextCell определяет следующие свойства:
Text
, типstring
, определяет основной текст, который будет отображаться.TextColor
ColorТип , представляет цвет первичного текста.Detail
, типstring
, определяет вторичный текст, который будет отображаться.DetailColor
ColorТип , указывает цвет вторичного текста.Command
ICommandТип , определяет команду, выполняемую при нажатии ячейки.CommandParameter
object
Тип , представляет параметр, переданный команде.
Эти свойства поддерживаются объектами BindableProperty, то есть эти свойства можно указывать в качестве целевых для привязки и стилизации данных.
В следующем примере показано, как TextCell определить внешний вид элементов в :ListView
<ListView ItemsSource="{Binding Food}">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name}"
Detail="{Binding Description}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
На следующем снимка экрана показана результирующая внешний вид ячейки:
Ячейка изображения
Отображает ImageCell изображение с первичным и вторичным текстом в отдельных строках. ImageCell наследует свойства от TextCellи определяет ImageSource свойство типа ImageSource, указывающее изображение, отображаемое в ячейке. Это свойство поддерживается BindableProperty объектом, что означает, что оно может быть целевым объектом привязок данных и стилем.
В следующем примере показано, как ImageCell определить внешний вид элементов в :ListView
<ListView ItemsSource="{Binding Food}">
<ListView.ItemTemplate>
<DataTemplate>
<ImageCell ImageSource="{Binding Image}"
Text="{Binding Name}"
Detail="{Binding Description}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
На следующем снимка экрана показана результирующая внешний вид ячейки:
Просмотр ячейки
A ViewCell — это настраиваемая ячейка, внешний вид которой определяется .View ViewCell определяет View свойство типа, Viewопределяющее представление, представляющее содержимое ячейки. Это свойство поддерживается BindableProperty объектом, что означает, что оно может быть целевым объектом привязок данных и стилем.
Примечание.
View — это свойство содержимого класса ViewCell. Поэтому его не нужно явно задавать из XAML.
В следующем примере показано, как ViewCell определить внешний вид элементов в :ListView
<ListView ItemsSource="{Binding Monkeys}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Grid.RowSpan="2"
Source="{Binding ImageUrl}"
Aspect="AspectFill"
HeightRequest="60"
WidthRequest="60" />
<Label Grid.Column="1"
Text="{Binding Name}"
FontAttributes="Bold" />
<Label Grid.Row="1"
Grid.Column="1"
Text="{Binding Location}"
FontAttributes="Italic"
VerticalOptions="End" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
ViewCellВнутри макета можно управлять любым макетом .NET MAUI. В этом примере макет управляется с Gridпомощью . Image Содержит Grid объект и два Label объекта, которые привязываются ко свойствам Monkey
класса.
На следующем снимке экрана показан результат создания шаблонов каждого элемента в списке:
Выбор внешнего вида элемента во время выполнения
Внешний вид каждого элемента в объекте ListView можно выбрать во время выполнения на основе значения элемента, задав свойству ItemTemplate
DataTemplateSelector объект:
<ContentPage ...
xmlns:templates="clr-namespace:ListViewDemos.Templates">
<ContentPage.Resources>
<DataTemplate x:Key="AmericanMonkeyTemplate">
<ViewCell>
...
</ViewCell>
</DataTemplate>
<DataTemplate x:Key="OtherMonkeyTemplate">
<ViewCell>
...
</ViewCell>
</DataTemplate>
<templates:MonkeyDataTemplateSelector x:Key="MonkeySelector"
AmericanMonkey="{StaticResource AmericanMonkeyTemplate}"
OtherMonkey="{StaticResource OtherMonkeyTemplate}" />
</ContentPage.Resources>
<StackLayout Margin="20">
<ListView ItemsSource="{Binding Monkeys}"
ItemTemplate="{StaticResource MonkeySelector}" />
</StackLayout>
</ContentPage>
Для ItemTemplate
свойства задан MonkeyDataTemplateSelector
объект. В следующем примере показан MonkeyDataTemplateSelector
класс:
public class MonkeyDataTemplateSelector : DataTemplateSelector
{
public DataTemplate AmericanMonkey { get; set; }
public DataTemplate OtherMonkey { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
return ((Monkey)item).Location.Contains("America") ? AmericanMonkey : OtherMonkey;
}
}
Класс MonkeyDataTemplateSelector
определяет AmericanMonkey
и OtherMonkey
DataTemplate свойства, которые задаются различными шаблонами данных. Переопределение OnSelectTemplate
возвращает AmericanMonkey
шаблон, который отображает имя обезьяны и расположение в подростке, когда имя обезьяны содержит "Америка". Если имя обезьяны не содержит "Америка", переопределение возвращает OtherMonkey
шаблон, OnSelectTemplate
который отображает имя обезьяны и расположение в серебре:
Дополнительные сведения о селекторах шаблонов данных см. в разделе "Создание объекта DataTemplateSelector".
Реагирование на выбор элемента
По умолчанию ListView выбор включен. Однако это поведение можно изменить, задав SelectionMode
свойство. Перечисление ListViewSelectionMode
определяет следующие члены:
None
— указывает, что элементы не могут быть выбраны.Single
— указывает, что можно выбрать один элемент с выделенным элементом. Это значение по умолчанию.
ListViewItemSelected
определяет событие, возникающее при SelectedItem
изменении свойства, из-за выбора элемента из списка или при установке свойства приложением. Объект SelectedItemChangedEventArgs
, сопровождающий это событие, имеет SelectedItem
и SelectedItemIndex
свойства.
SelectionMode
Если для свойства задано Single
значение, можно выбрать один элемент в элементеListView. При выборе SelectedItem
элемента свойство будет задано значение выбранного элемента. При изменении ItemSelected
этого свойства вызывается событие.
В следующем примере показано ListView , что может реагировать на выбор одного элемента:
<ListView ItemsSource="{Binding Monkeys}"
ItemSelected="OnItemSelected">
...
</ListView>
В этом примере OnItemSelected
обработчик событий выполняется при ItemSelected
срабатывании события с помощью обработчика событий, извлекающего выбранный элемент:
void OnItemSelected(object sender, SelectedItemChangedEventArgs args)
{
Monkey item = args.SelectedItem as Monkey;
}
На следующем снимке экрана показан выбор одного элемента в :ListView
Очистка выделенного фрагмента
Свойство SelectedItem
можно очистить, задав его или объект, к которым он привязывается.null
Отключение выделения
ListView Выбор включен по умолчанию. Однако его можно отключить, задав SelectionMode
для свойства значение None
:
<ListView ...
SelectionMode="None" />
SelectionMode
Если для свойства задано None
значение , элементы в ListView ней не могут быть выбраны, SelectedItem
свойство останется null
и ItemSelected
событие не будет запущено.
Кэширование данных
ListView — это мощное представление для отображения данных, но оно имеет некоторые ограничения. Производительность прокрутки может страдать при использовании пользовательских ячеек, особенно если они содержат иерархии глубоко вложенных представлений или используют определенные макеты, требующие сложного измерения. К счастью, есть методы, которые можно использовать, чтобы избежать плохой производительности.
Часто ListView используется для отображения гораздо большего объема данных, чем на экране. Например, у музыкального приложения может быть библиотека песен с тысячами записей. Создание элемента для каждой записи будет тратить ценную память и плохо работать. Постоянно создавая и уничтожая строки, приложение будет постоянно создавать экземпляры и очищать объекты, которые также будут работать плохо.
Для экономии памяти собственные ListView эквиваленты для каждой платформы имеют встроенные функции для повторного использования строк. Только ячейки, видимые на экране, загружаются в память, а содержимое загружается в существующие ячейки. Этот шаблон не позволяет приложению создавать экземпляры тысяч объектов, сохранять время и память.
.NET MAUI разрешает ListView повторное использование ячеек через ListViewCachingStrategy
перечисление, которое определяет следующие элементы:
RetainElement
, указывает, что ListView ячейка будет создаваться для каждого элемента в списке.RecycleElement
Указывает, что ListView попытка свести к минимуму объем памяти и скорость выполнения путем перезапуска ячеек списка.RecycleElementAndDataTemplate
, какRecycleElement
и обеспечение того, что при ListView использовании DataTemplateSelectorDataTemplate объекта объекты кэшируются типом элемента в списке.
Сохранение элементов
Стратегия RetainElement
кэширования указывает, что ListView будет создавать ячейку для каждого элемента в списке и является поведением по умолчанию ListView . Его следует использовать в следующих обстоятельствах:
- Каждая ячейка имеет большое количество привязок (20–30+).
- Шаблон ячейки часто изменяется.
- Тестирование показывает, что
RecycleElement
стратегия кэширования приводит к снижению скорости выполнения.
Важно распознать последствия RetainElement
стратегии кэширования при работе с пользовательскими ячейками. Любой код инициализации ячеек должен выполняться для каждого создания ячейки, что может быть несколько раз в секунду. В этом случае методы макета, которые были тонкими на странице, как использование нескольких вложенных StackLayout объектов, становятся узкими местами производительности при настройке и уничтожении в режиме реального времени при прокрутке пользователя.
Корзина элементов
Стратегия RecycleElement
кэширования указывает, что ListView попытка свести к минимуму объем памяти и скорость выполнения путем перезапуска ячеек списка. Этот режим не всегда предлагает улучшение производительности и тестирование должно выполняться для определения каких-либо улучшений. Тем не менее, это предпочтительный выбор, и его следует использовать в следующих обстоятельствах:
- Каждая ячейка имеет небольшое или умеренное количество привязок.
- Каждая ячейка
BindingContext
определяет все данные ячейки. - Каждая ячейка в значительной степени аналогична шаблону ячейки.
Во время виртуализации ячейка будет обновлять контекст привязки и поэтому, если приложение использует этот режим, оно должно убедиться, что обновления контекста привязки обрабатываются соответствующим образом. Все данные о ячейке должны поступать из контекста привязки или ошибок согласованности. Эту проблему можно избежать с помощью привязки данных для отображения данных ячейки. Кроме того, данные ячеек должны быть заданы в переопределении, а не в OnBindingContextChanged
конструкторе пользовательской ячейки, как показано в следующем примере:
public class CustomCell : ViewCell
{
Image image = null;
public CustomCell()
{
image = new Image();
View = image;
}
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
var item = BindingContext as ImageItem;
if (item != null)
{
image.Source = item.ImageUrl;
}
}
}
Корзина элементов с помощью dataTemplateSelector
Если используется ListViewDataTemplateSelector для выбора DataTemplate, RecycleElement
стратегия кэширования не кэширует DataTemplate объекты. Вместо этого выбирается для DataTemplate каждого элемента данных в списке.
Примечание.
Стратегия RecycleElement
кэширования требует, чтобы при DataTemplateSelector запросе выбрать DataTemplate то, что каждый должен возвращать один DataTemplate и тот же ViewCell тип. Например, если задано ListView значение, DataTemplateSelector которое может возвращать MyDataTemplateA
либо (где MyDataTemplateA
возвращает типMyViewCellA
), либо MyDataTemplateB
(где MyDataTemplateB
возвращает ViewCellMyViewCellB
ViewCell тип), когда MyDataTemplateA
возвращается он должен возвращать MyViewCellA
или возникает исключение.
Корзина элементов с dataTemplates
Стратегия RecycleElementAndDataTemplate
кэширования основывается на RecycleElement
стратегии кэширования, дополнительно гарантируя, что при ListView использовании DataTemplateSelector выбранного DataTemplateDataTemplate объекта объекты кэшируются типом элемента в списке. Таким образом, DataTemplate объекты выбираются один раз на тип элемента вместо одного экземпляра элемента.
Примечание.
Стратегия RecycleElementAndDataTemplate
кэширования требует, чтобы DataTemplate объекты, возвращаемые DataTemplateSelector конструктором DataTemplate , который принимает Type
объект.
Настройка стратегии кэширования
ListView Стратегия кэширования может быть определена в XAML, задав CachingStrategy
атрибут:
<ListView CachingStrategy="RecycleElement">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
...
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
В C#стратегия кэширования устанавливается через перегрузку конструктора:
ListView listView = new ListView(ListViewCachingStrategy.RecycleElement);
Настройка стратегии кэширования в подклассном ListView
CachingStrategy
Задание атрибута из XAML в подклассе ListView не приведет к возникновению требуемого поведения, так как в ней нет CachingStrategy
свойстваListView. Решение этой проблемы заключается в указании конструктора подкласса ListView , который принимает ListViewCachingStrategy
параметр и передает его базовому классу:
public class CustomListView : ListView
{
public CustomListView (ListViewCachingStrategy strategy) : base (strategy)
{
}
...
}
ListViewCachingStrategy
Затем значение перечисления можно указать из XAML с помощью атрибутаx:Arguments
:
<local:CustomListView>
<x:Arguments>
<ListViewCachingStrategy>RecycleElement</ListViewCachingStrategy>
</x:Arguments>
</local:CustomListView>
Колонтитулы
ListView может представлять верхний и нижний колонтитул, прокручиваемый элементами в списке. Верхний и нижний колонтитул могут быть строками, представлениями или DataTemplate объектами.
ListView определяет следующие свойства для указания верхнего и нижнего колонтитула:
Header
object
Тип , указывает строку, привязку или представление, которое будет отображаться в начале списка.HeaderTemplate
, тип DataTemplate, указывает DataTemplate , что используется для форматированияHeader
.Footer
object
Тип , указывает строку, привязку или представление, которое будет отображаться в конце списка.FooterTemplate
, тип DataTemplate, указывает DataTemplate , что используется для форматированияFooter
.
Эти свойства поддерживаются BindableProperty объектами, что означает, что свойства могут быть целевыми объектами привязки данных.
Отображение строк в верхнем и нижнем колонтитуле
Значения Header
и Footer
свойства можно задать string
, как показано в следующем примере:
<ListView ItemsSource="{Binding Monkeys}"
Header="Monkeys"
Footer="2022">
...
</ListView>
На следующем снимка экрана показан итоговый заголовок:
Отображение представлений в верхнем и нижнем колонтитуле
Для Header
каждого Footer
свойства можно задать представление. Это может быть одно представление или представление, содержащее несколько дочерних представлений. В следующем примере показаны Header
свойства каждого Footer
набора StackLayout для объекта, содержащего Label объект:
<ListView ItemsSource="{Binding Monkeys}">
<ListView.Header>
<StackLayout BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Text="Monkeys"
FontSize="12"
FontAttributes="Bold" />
</StackLayout>
</ListView.Header>
<ListView.Footer>
<StackLayout BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Text="Friends of Monkey"
FontSize="12"
FontAttributes="Bold" />
</StackLayout>
</ListView.Footer>
...
</ListView>
На следующем снимка экрана показан итоговый заголовок:
Отображение шаблона верхнего и нижнего колонтитула
FooterTemplate
Свойства HeaderTemplate
можно задать для DataTemplate объектов, которые используются для форматирования верхнего и нижнего колонтитулов. В этом сценарии Header
Footer
свойства должны привязаться к текущему источнику для применения шаблонов, как показано в следующем примере:
<ListView ItemsSource="{Binding Monkeys}"
Header="{Binding .}"
Footer="{Binding .}">
<ListView.HeaderTemplate>
<DataTemplate>
<StackLayout BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Text="Monkeys"
FontSize="12"
FontAttributes="Bold" />
</StackLayout>
</DataTemplate>
</ListView.HeaderTemplate>
<ListView.FooterTemplate>
<DataTemplate>
<StackLayout BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Text="Friends of Monkey"
FontSize="12"
FontAttributes="Bold" />
</StackLayout>
</DataTemplate>
</ListView.FooterTemplate>
...
</ListView>
Разделители элементов управления
По умолчанию разделители отображаются между ListView элементами в iOS и Android. Это поведение можно изменить, задав SeparatorVisibility
для свойства тип SeparatorVisibility
, значение None
:
<ListView ...
SeparatorVisibility="None" />
Кроме того, если разделитель включен, его цвет можно задать со свойством SeparatorColor
:
<ListView ...
SeparatorColor="Blue" />
Элементы размера
По умолчанию все элементы в ListView одном и том же высоте, что является производным от содержимого элемента, определяющего DataTemplate внешний вид каждого элемента. Однако это поведение можно изменить с помощью HasUnevenRows
свойств и RowHeight
свойств. По умолчанию HasUnevenRows
свойство равно false
.
Для RowHeight
свойства можно задать int
значение, представляющее высоту каждого элемента в заданном ListViewобъекте HasUnevenRows
false
. Если HasUnevenRows
задано значение true
, каждый элемент в элементе ListView может иметь другую высоту. Высота каждого элемента будет производным от содержимого элемента DataTemplate, поэтому каждый элемент будет иметь размер в его содержимом.
Отдельные ListView элементы могут быть программно изменены во время выполнения путем изменения свойств, связанных с макетом элементов внутри DataTemplateэлемента, при условии, что HasUnevenRows
это свойство true
. В следующем примере изменяется высота Image объекта при нажатии:
void OnImageTapped(object sender, EventArgs args)
{
Image image = sender as Image;
ViewCell viewCell = image.Parent.Parent as ViewCell;
if (image.HeightRequest < 250)
{
image.HeightRequest = image.Height + 100;
viewCell.ForceUpdateSize();
}
}
В этом примере OnImageTapped
обработчик событий выполняется в ответ на Image касания объекта. Обработчик событий обновляет высоту ImageCell.ForceUpdateSize
и метод обновляет размер ячейки, даже если она в настоящее время не отображается.
Предупреждение
Чрезмерное использование динамического размера элементов может привести ListView к снижению производительности.
Макет справа налево
ListView может макетировать содержимое в направлении потока справа налево, задав для свойства значение FlowDirection
RightToLeft
. FlowDirection
Однако свойство в идеале должно быть задано на странице или корневом макете, что приводит ко всем элементам страницы или корневому макету для реагирования на направление потока:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ListViewDemos.RightToLeftListPage"
Title="Right to left list"
FlowDirection="RightToLeft">
<StackLayout Margin="20">
<ListView ItemsSource="{Binding Monkeys}">
...
</ListView>
</StackLayout>
</ContentPage>
Значение по умолчанию FlowDirection
для элемента с родительским MatchParent
элементом . Поэтому значение ListView свойства наследуется FlowDirection
от StackLayoutзначения, которое, в свою очередь, наследует FlowDirection
значение свойства от ContentPage.
Отображение сгруппированных данных
Большие наборы данных часто становятся неуправляемыми при постоянной прокрутке списка. В этом сценарии упорядочение данных в группы может улучшить взаимодействие с пользователем, упрощая навигацию по данным.
Перед отображением данных необходимо сгруппировать. Это можно сделать, создав список групп, где каждая группа является списком элементов. Список групп должен быть коллекцией IEnumerable<T>
, где T
определяется два фрагмента данных:
- Имя группы.
- Коллекция
IEnumerable
, определяющая элементы, принадлежащие группе.
Таким образом, процесс группировки данных заключается в том, чтобы:
- Создайте тип, который моделирует один элемент.
- Создайте тип, который моделирует одну группу элементов.
- Создайте коллекцию
IEnumerable<T>
, гдеT
используется тип, который моделирует одну группу элементов. Эта коллекция представляет собой коллекцию групп, в которой хранятся сгруппированные данные. - Добавьте данные в коллекцию
IEnumerable<T>
.
Пример
При группировке данных первым шагом является создание типа, моделирующего один элемент. В следующем примере показан Animal
класс:
public class Animal
{
public string Name { get; set; }
public string Location { get; set; }
public string Details { get; set; }
public string ImageUrl { get; set; }
}
Класс Animal
моделирует один элемент. Затем можно создать тип, который моделирует группу элементов. В следующем примере показан AnimalGroup
класс:
public class AnimalGroup : List<Animal>
{
public string Name { get; private set; }
public AnimalGroup(string name, List<Animal> animals) : base(animals)
{
Name = name;
}
}
Класс AnimalGroup
наследует от List<T>
класса и добавляет Name
свойство, представляющее имя группы.
Затем можно создать коллекцию IEnumerable<T>
групп:
public List<AnimalGroup> Animals { get; private set; } = new List<AnimalGroup>();
Этот код определяет коллекцию с именем Animals
, где каждый элемент в коллекции является AnimalGroup
объектом. Каждый AnimalGroup
объект состоит из имени и List<Animal>
коллекции, которая определяет Animal
объекты в группе.
Затем группированные данные можно добавить в коллекцию Animals
:
Animals.Add(new AnimalGroup("Bears", new List<Animal>
{
new Animal
{
Name = "American Black Bear",
Location = "North America",
Details = "Details about the bear go here.",
ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/0/08/01_Schwarzbär.jpg"
},
new Animal
{
Name = "Asian Black Bear",
Location = "Asia",
Details = "Details about the bear go here.",
ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b7/Ursus_thibetanus_3_%28Wroclaw_zoo%29.JPG/180px-Ursus_thibetanus_3_%28Wroclaw_zoo%29.JPG"
},
// ...
}));
Animals.Add(new AnimalGroup("Monkeys", new List<Animal>
{
new Animal
{
Name = "Baboon",
Location = "Africa & Asia",
Details = "Details about the monkey go here.",
ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Papio_anubis_%28Serengeti%2C_2009%29.jpg/200px-Papio_anubis_%28Serengeti%2C_2009%29.jpg"
},
new Animal
{
Name = "Capuchin Monkey",
Location = "Central & South America",
Details = "Details about the monkey go here.",
ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/40/Capuchin_Costa_Rica.jpg/200px-Capuchin_Costa_Rica.jpg"
},
new Animal
{
Name = "Blue Monkey",
Location = "Central and East Africa",
Details = "Details about the monkey go here.",
ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/BlueMonkey.jpg/220px-BlueMonkey.jpg"
},
// ...
}));
Этот код создает две группы в Animals
коллекции. Первый AnimalGroup
называется Bears
и содержит коллекцию List<Animal>
сведений о медведе. Второй AnimalGroup
называется Monkeys
и содержит коллекцию List<Animal>
подробностей обезьяны.
ListView отображает сгруппированные данные, если данные были правильно сгруппированы, задав IsGroupingEnabled
для свойства true
значение :
<ListView ItemsSource="{Binding Animals}"
IsGroupingEnabled="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Grid.RowSpan="2"
Source="{Binding ImageUrl}"
Aspect="AspectFill"
HeightRequest="60"
WidthRequest="60" />
<Label Grid.Column="1"
Text="{Binding Name}"
FontAttributes="Bold" />
<Label Grid.Row="1"
Grid.Column="1"
Text="{Binding Location}"
FontAttributes="Italic"
VerticalOptions="End" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Эквивалентный код на C# выглядит так:
ListView listView = new ListView
{
IsGroupingEnabled = true
};
listView.SetBinding(ItemsView.ItemsSourceProperty, "Animals");
// ...
Внешний вид каждого элемента в объекте ListView определяется путем задания его ItemTemplate
свойства в значение DataTemplate. Дополнительные сведения см. в разделе "Определение внешнего вида элемента".
На следующем снимка экрана показан ListView сгруппированные данные:
Примечание.
По умолчанию ListView отобразится имя группы в заголовке группы. Это поведение можно изменить, настроив заголовок группы.
Настройка заголовка группы
Внешний вид каждого заголовка группы можно настроить, задав ListView.GroupHeaderTemplate
для свойства значение DataTemplate:
<ListView ItemsSource="{Binding Animals}"
IsGroupingEnabled="True">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding Name}"
BackgroundColor="LightGray"
FontSize="18"
FontAttributes="Bold" />
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
...
</ListView>
В этом примере для каждого заголовка группы задано Label значение, отображающее имя группы и которое имеет другие свойства внешнего вида. На следующем снимка экрана показан заголовок настраиваемой группы:
Важно!
Свойство GroupHeaderTemplate
является взаимоисключающим с свойством GroupDisplayBinding
. Поэтому оба свойства не должны быть заданы.
Группа без шаблонов
ListViewможет отображать правильно сгруппированные данные, не устанавливая для DataTemplateсвойства значение ItemTemplate
:
<ListView ItemsSource="{Binding Animals}"
IsGroupingEnabled="true" />
В этом сценарии значимые данные можно отобразить, переопределив метод в типе, который моделирует ToString
один элемент, и тип, который моделирует одну группу элементов.
Управление прокруткой
ListView определяет два ScrollTo
метода, которые прокручивают элементы в представление. Одна из перегрузок прокручивает указанный элемент в представление, а другая прокручивает указанный элемент в указанной группе в представление. Обе перегрузки имеют дополнительные аргументы, позволяющие точное положение элемента после завершения прокрутки, а также необходимость анимации прокрутки.
ListViewScrollToRequested
определяет событие, которое запускается при вызове ScrollTo
одного из методов. ОбъектScrollToRequestedEventArgs
, сопровождающий ScrollToRequested
событие, имеет множество свойств, включая ShouldAnimate
, ElementMode
и Position
. Некоторые из этих свойств задаются из аргументов, указанных в ScrollTo
вызовах метода.
Кроме того, ListView определяет Scrolled
событие, которое запускается, чтобы указать, что произошла прокрутка. Объект ScrolledEventArgs
, сопровождающий Scrolled
событие, имеет ScrollX
и ScrollY
свойства.
Обнаружение прокрутки
ListViewScrolled
определяет событие, которое запускается, чтобы указать, что произошла прокрутка. Класс ItemsViewScrolledEventArgs
, представляющий объект, который сопровождает Scrolled
событие, определяет следующие свойства:
ScrollX
, типdouble
, представляет положение X прокруткиScrollY
double
тип , представляет положение Y прокрутки.
В следующем примере XAML показан ListView обработчик событий для Scrolled
события:
<ListView Scrolled="OnListViewScrolled">
...
</ListView>
Эквивалентный код на C# выглядит так:
ListView listView = new ListView();
listView.Scrolled += OnListViewScrolled;
В этом примере OnListViewScrolled
кода обработчик событий выполняется при Scrolled
срабатывании события:
void OnListViewScrolled(object sender, ScrolledEventArgs e)
{
// Custom logic
}
Важно!
Событие Scrolled
запускается для прокручиваемых пользователем прокрутк и для программных прокрутк.
Прокрутка элемента в представление
Метод ScrollTo
прокручивает указанный элемент в представление. Учитывая ListView объект с именем listView
, в следующем примере показано, как прокрутить элемент Обезьяны Proboscis в представление:
MonkeysViewModel viewModel = BindingContext as MonkeysViewModel;
Monkey monkey = viewModel.Monkeys.FirstOrDefault(m => m.Name == "Proboscis Monkey");
listView.ScrollTo(monkey, ScrollToPosition.MakeVisible, true);
Кроме того, элемент в сгруппированных данных можно прокрутить в представление, указав элемент и группу. В следующем примере показано, как прокрутить элемент Обезьяны Proboscis в группе "Обезьяны" в представление:
GroupedAnimalsViewModel viewModel = BindingContext as GroupedAnimalsViewModel;
AnimalGroup group = viewModel.Animals.FirstOrDefault(a => a.Name == "Monkeys");
Animal monkey = group.FirstOrDefault(m => m.Name == "Proboscis Monkey");
listView.ScrollTo(monkey, group, ScrollToPosition.MakeVisible, true);
Примечание.
Событие ScrollToRequested
запускается при вызове ScrollTo
метода.
Отключение анимации прокрутки
Анимация прокрутки отображается при прокрутке элемента в представление. Однако эту анимацию можно отключить, задав animated
аргумент ScrollTo
метода false
следующим образом:
listView.ScrollTo(monkey, position: ScrollToPosition.MakeVisible, animate: false);
Положение прокрутки элемента управления
При прокрутке элемента в представление точное положение элемента после завершения прокрутки можно указать с position
аргументом ScrollTo
методов. Этот аргумент принимает ScrollToPosition
член перечисления.
MakeVisible
Элемент ScrollToPosition.MakeVisible
указывает, что элемент должен быть прокручен до тех пор, пока он не отображается в представлении:
listView.ScrollTo(monkey, position: ScrollToPosition.MakeVisible, animate: true);
Начать с
Элемент ScrollToPosition.Start
указывает, что элемент должен прокручиваться до начала представления:
listView.ScrollTo(monkey, position: ScrollToPosition.Start, animate: true);
Центр
Элемент ScrollToPosition.Center
указывает, что элемент должен быть прокручен в центр представления:
listView.ScrollTo(monkey, position: ScrollToPosition.Center, animate: true);
Завершить
Элемент ScrollToPosition.End
указывает, что элемент должен быть прокручен до конца представления:
listView.ScrollTo(monkey, position: ScrollToPosition.End, animate: true);
Видимость полосы прокрутки
ListViewHorizontalScrollBarVisibility
определяет и VerticalScrollBarVisibility
свойства, которые поддерживаются привязываемыми свойствами. Эти свойства получают или задают ScrollBarVisibility
значение перечисления, представляющее, когда отображается горизонтальная или вертикальная полоса прокрутки. Перечисление ScrollBarVisibility
определяет следующие члены:
Default
указывает поведение полосы прокрутки по умолчанию для платформы и является значением по умолчанию дляHorizontalScrollBarVisibility
свойств иVerticalScrollBarVisibility
свойств.Always
указывает, что полосы прокрутки будут видимыми, даже если содержимое помещается в представление.Never
указывает, что полосы прокрутки не будут видимыми, даже если содержимое не помещается в представление.
Добавление контекстных меню
ListView поддерживает элементы контекстного меню, которые определяются как MenuItem объекты, добавляемые в коллекцию ViewCell.ContextActions
в каждом элементе DataTemplate :
<ListView x:Name="listView"
ItemsSource="{Binding Monkeys}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Text="Favorite"
Command="{Binding Source={x:Reference listView}, Path=BindingContext.FavoriteCommand}"
CommandParameter="{Binding}" />
<MenuItem Text="Delete"
Command="{Binding Source={x:Reference listView}, Path=BindingContext.DeleteCommand}"
CommandParameter="{Binding}" />
</ViewCell.ContextActions>
...
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Объекты MenuItem отображаются при щелчке элемента правой ListView кнопкой мыши:
Дополнительные сведения о элементах меню см. в разделе "Отображение элементов меню".
Потяните, чтобы обновить
ListView поддерживает вытягивание для обновления функциональных возможностей, что позволяет обновлять данные, отображаемые путем извлечения списка элементов.
Чтобы включить обновление по запросу IsPullToRefreshEnabled
, задайте для свойства значение true
. При активации ListView обновления вызывает Refreshing
событие, а IsRefreshing
свойство будет задано true
. Код, необходимый для обновления содержимого ListView , затем должен выполняться обработчиком события Refreshing
или ICommand реализацией RefreshCommand
выполнения. ListView После обновления IsRefreshing
свойство должно быть задано false
или EndRefresh
метод должен вызываться для объектаListView, чтобы указать, что обновление завершено.
В следующем примере показано ListView , как использовать вытягивание для обновления:
<ListView ItemsSource="{Binding Animals}"
IsPullToRefreshEnabled="true"
RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsRefreshing}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
...
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
В этом примере, когда пользователь инициирует обновление, выполняется свойство, ICommandRefreshCommand
которое должно обновить отображаемые элементы. Визуализация обновления отображается во время обновления, которая состоит из анимированного круга хода выполнения. Значение IsRefreshing
свойства указывает текущее состояние операции обновления. При активации обновления это свойство автоматически перейдет в true
. После завершения обновления необходимо сбросить свойство false
в значение .
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по