ListView и работа с данными

ListView

Последнее обновление: 22.01.2023

ListView представляет очень мощный элемет управления .NET MAUI, который позволяет отображать список объектов и при этом кастомизировать их отображение.

ListView связывается с набором данных через свойство ItemsSource, которое принимает объект IEnumerable<T>.

Создание ListView в коде C#

Определим в коде C# объект ListView, который выводит массив строк:

namespace HelloApp;

class StartPage : ContentPage
{
    public StartPage()
    {
        Label header = new Label{ Text = "Список пользователей" };
        // данные для ListView
        string[] people = new string[] { "Tom", "Bob", "Sam", "Alice" };

        ListView listView = new ListView();
        // определяем источник данных
        listView.ItemsSource = people;
        Content = new StackLayout { Children = { header, listView }, Padding=7};
    }
}
ItemsSource в ListView в .NET MAUI и C#

При выводе каждого объекта ListView по умолчанию вызывает для него метод ToString(), поэтому мы увидим строковое отображение объекта.

ListView в XAML

Аналогичный массив в 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">
    <StackLayout>
        <Label Text="Список пользователей"/>
        <ListView>
            <ListView.ItemsSource>
                <x:Array Type="{x:Type x:String}">
                    <x:String>Tom</x:String>
                    <x:String>Bob</x:String>
                    <x:String>Sam</x:String>
                    <x:String>Alice</x:String>
                </x:Array>
            </ListView.ItemsSource>
        </ListView>
    </StackLayout>
</ContentPage>

Здесь напрямую определяется массив строк для свойства ListView.ItemsSource. Однако обычно данные определяются вне, например, в виде ресурса:

<?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">
    <ContentPage.Resources>
        <ResourceDictionary>
            <x:Array x:Key="people" Type="{x:Type x:String}">
                <x:String>Tomas</x:String>
                <x:String>Bob</x:String>
                <x:String>Sam</x:String>
                <x:String>Alice</x:String>
            </x:Array>
        </ResourceDictionary>
    </ContentPage.Resources>
    <StackLayout>
        <Label Text="Список пользователей"/>
        <ListView ItemsSource="{StaticResource people}" />
    </StackLayout>
</ContentPage>

Сочетание XAML и C#. Привязка к списку

Нередко источник данных для ListView определяется в коде C#. И в этом случае мы можем использовать привязку к источнику данных. Например, в коде C# у страницы MainPage определим список строк, к которому будет производиться привязка:

namespace HelloApp;

public partial class MainPage : ContentPage
{
    public List<string> Users { get; set; }
    public MainPage()
	{
		InitializeComponent();
        Users = new List<string> { "Tom", "Bob", "Sam", "Alice" };
        BindingContext = this;
    }
}

Стоит отметить, что источник данных определен как публичное свойство Users. Другой важный момент - установка контекста привязки страницы: BindingContext = this;. Таким образом, в XAML мы можем обратиться ко всем публичным свойствам страницы.

В коде XAML страницы MainPage пропишем привязку к этому свойству:

<?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">
    <StackLayout>
        <Label Text="Список пользователей"/>
        <ListView ItemsSource="{Binding Users}" />
    </StackLayout>
</ContentPage>

Обработка выбора элемента

Когда пользователь нажимает на элемент списка, он выделяется, а у ListView срабатывают два события: ItemTapped и ItemSelected. Между ними есть различия. Так, повторное нажатие на один и тот же элемент не вызовет повторного события ItemSelected, так как элемент остается выбанным. А вот событие ItemTapped будет срабатывать именно столько раз сколько пользователь нажал на него, даже повторно. Также событие ItemSelected будет вызвано, если с элемента будет снято выделение.

ItemSelected

Обработаем выделение элемента. Для этого определим следующий код в MainPage.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">
    <StackLayout Padding="7">
        <Label x:Name="selected"/>
        <ListView x:Name="usersList" ItemSelected="usersList_ItemSelected" />
    </StackLayout>
</ContentPage>

А в файле кода MainPage.xaml.cs определим источник данных и обработчик события ItemSelected:

namespace HelloApp;

public partial class MainPage : ContentPage
{
    public MainPage()
	{
		InitializeComponent();
        usersList.ItemsSource = new List<string> { "Tom", "Bob", "Sam", "Alice" };
    }
    private void usersList_ItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
        selected.Text = $"Выбрано: {e.SelectedItem}";
    }
}

При выборе элемента мы можем получить выбранный элемент через свойство SelectedItem объекта SelectedItemChangedEventArgs, который передается в качестве параметра.

Поскольку список содержит массив строк, то каждый его элемент представляет строку, которую мы можем получить с помощью метода e.SelectedItem.ToString().

Событие ItemsSelected в ListView и обработка выбора элемента в списке в .NET MAUI и C#

ItemTapped

Похожим образом можно обработать событие ItemTapped. Определим в 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">
    <StackLayout Padding="7">
        <Label x:Name="selected"/>
        <ListView x:Name="usersList" ItemTapped="usersList_ItemTapped" />
    </StackLayout>
</ContentPage>

А в файле кода MainPage.xaml.cs определим источник данных и обработчик события ItemTapped:

namespace HelloApp;

public partial class MainPage : ContentPage
{
    public MainPage()
	{
		InitializeComponent();
        usersList.ItemsSource = new List<string> { "Tom", "Bob", "Sam", "Alice" };
    }
    private void usersList_ItemTapped(object sender, ItemTappedEventArgs e)
    {
        selected.Text = $"Нажато: {e.Item}";
    }
}

Привязка к выбранному элементу

Обработчики событий нажатия и выбора элементы хороши, если нам надо выполнить некоторую логику, связанную с этим элементом. Однако если нам надо просто вывести выбранный элемент в метку, то мы можем просто установить привязку к выбранному в ListView элементу. В примере выше мы вполне могли бы обойтись без обработки события и просто установить привязку элемента Label к выбранному объекту списка. Выбранный элемент в ListView хранится в свойстве SelectItem:

<?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">
    <ContentPage.Resources>
        <ResourceDictionary>
            <x:Array x:Key="users" Type="{x:Type x:String}">
                <x:String>Tom</x:String>
                <x:String>Bob</x:String>
                <x:String>Sam</x:String>
                <x:String>Alice</x:String>
            </x:Array>
        </ResourceDictionary>
    </ContentPage.Resources>
    <StackLayout Padding="7">
        <Label Text="{Binding Source={Reference usersList}, Path=SelectedItem}" />
        <ListView x:Name="usersList" ItemsSource="{StaticResource users}" />
    </StackLayout>
</ContentPage>

В данном случае свойство Text метки привязано к свойству SelectedItem элемента usersList. И при изменении выбранного элемента в ListView метка также изменить свой текст.

Привязка к SelectedItem в ListView и обработка выбора элемента в списке в .NET MAUI и C#

Установка привязке в коде C#:

namespace HelloApp;

class StartPage : ContentPage
{
    public StartPage()
    {
        Label header = new Label();

        ListView usersList = new ListView();
        // определяем источник данных
        usersList.ItemsSource = new string[] { "Tomas", "Bob", "Sam", "Alice" };
        // установка привязки к SelectedItem
        header.SetBinding(Label.TextProperty, new Binding { Source= usersList, Path ="SelectedItem" });
        Content = new StackLayout { Children = { header, usersList }, Padding=7};
    }
}

Высота строк

Свойство RowHeight позволяет задать высоту строки в ListView. Но действовать оно будет только в том случае, если другое свойство в ListView - HasUnevenRows равно false (значение по умолчанию).

Установка в XAML:

<ListView RowHeight="100" >

В коде C#:

listView.RowHeight = 100;
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850