ObservableCollection

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

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

public class User
{
    public string Name { get; set; } = "";
    public int Age { get; set; }
}

Определим на странице элемент ListView для вывода списка объектов User и поля для добавления одного объекта в список:

namespace HelloApp;

class StartPage : ContentPage
{
    public List<User> Users { get; set; }
    Entry nameEntry, ageEntry;

    public StartPage()
    {
        // определяем данные
        Users = new List<User>
        {
            new User {Name="Tom", Age=38 },
            new User {Name = "Bob", Age = 42}
        };
        ListView listView = new ListView();
        // определяем источник данных
        listView.ItemsSource = Users;
        // определяем шаблон данных
        listView.ItemTemplate = new DataTemplate(() =>
        {
            // привязка к свойству Name
            Label nameLabel = new Label { FontSize = 16 };
            nameLabel.SetBinding(Label.TextProperty, "Name");

            // привязка к свойству Age
            Label ageLabel = new Label { FontSize = 14 };
            ageLabel.SetBinding(Label.TextProperty, "Age");

            // создаем объект ViewCell.
            return new ViewCell
            {
                View = new StackLayout
                {
                    Padding = new Thickness(0, 5),
                    Orientation = StackOrientation.Vertical,
                    Children = { nameLabel, ageLabel }
                }
            };
        });

        // поля для добавления нового объекта User
        nameEntry = new Entry { Placeholder = "Enter name", Margin=5 };
        ageEntry = new Entry { Placeholder = "Enter age", Margin=5 };
        Button saveButton = new Button { Text = "Save", WidthRequest=100, Margin=5, HorizontalOptions = LayoutOptions.Start };
        saveButton.Clicked += SaveButton_Clicked;
        StackLayout form = new StackLayout
        {
            Orientation = StackOrientation.Vertical,
            Children = { nameEntry, ageEntry, saveButton }
        };
        Content = new StackLayout { Children = { form, listView }, Padding=7};
    }

    private void SaveButton_Clicked(object sender, EventArgs e)
    {
        int.TryParse(ageEntry.Text, out var age);
        Users.Add(new User { Name = nameEntry.Text, Age = age });
        nameEntry.Text = ageEntry.Text = "";
    }
}

На странице определена форма для добавления в список Users. В данном случае типом коллекции Users является стандартный класс List, который поддерживает добавление с помощью методов Add(). По нажатию кнопки срабатывает обработчик SaveButton_Clicked, в котором берем из текстовых полей введенные значения, на их основе создаем объект User и добавляем его в список. Мы ожидаем, что после добавления нового пользователя в список Users также обновится и ListView.

Добавление в список ListView в .NET MAUI и C#

Однако после добавления ListView не будет отображать добавленные объекты.

Чтобы решить эту проблемы в качестве типа коллекции, как правило, используется не класс List, а класс ObservableCollection из пространства имен System.Collections.ObjectModel. За счет реализации интерфейса INotifyCollectionChanged при добавлении или удалении объектов в ObservableCollection автоматически будут изменяться все привязанные к этой коллекции объекты, в том числе и ListView.

Итак, изменим тип коллекции Users:

using System.Collections.ObjectModel;

namespace HelloApp;

class StartPage : ContentPage
{
    public ObservableCollection<User> Users { get; set; }
    Entry nameEntry, ageEntry;

    public StartPage()
    {
        // определяем данные
        Users = new ObservableCollection<User>
        {
            new User {Name="Tom", Age=38 },
            new User {Name = "Bob", Age = 42}
        };
        ListView listView = new ListView();
        // определяем источник данных
        listView.ItemsSource = Users;
        // определяем шаблон данных
        listView.ItemTemplate = new DataTemplate(() =>
        {
            // привязка к свойству Name
            Label nameLabel = new Label { FontSize = 16 };
            nameLabel.SetBinding(Label.TextProperty, "Name");

            // привязка к свойству Age
            Label ageLabel = new Label { FontSize = 14 };
            ageLabel.SetBinding(Label.TextProperty, "Age");

            // создаем объект ViewCell.
            return new ViewCell
            {
                View = new StackLayout
                {
                    Padding = new Thickness(0, 5),
                    Orientation = StackOrientation.Vertical,
                    Children = { nameLabel, ageLabel }
                }
            };
        });

        // поля для добавления нового объекта User
        nameEntry = new Entry { Placeholder = "Enter name", Margin=5 };
        ageEntry = new Entry { Placeholder = "Enter age", Margin=5 };
        Button saveButton = new Button { Text = "Save", WidthRequest=100, Margin=5, HorizontalOptions = LayoutOptions.Start };
        saveButton.Clicked += SaveButton_Clicked;
        StackLayout form = new StackLayout
        {
            Orientation = StackOrientation.Vertical,
            Children = { nameEntry, ageEntry, saveButton }
        };
        Content = new StackLayout { Children = { form, listView }, Padding=7};
    }

    private void SaveButton_Clicked(object sender, EventArgs e)
    {
        int.TryParse(ageEntry.Text, out var age);
        Users.Add(new User { Name = nameEntry.Text, Age = age });
        nameEntry.Text = ageEntry.Text = "";
    }
}

Теперь все будет нормально добавляться

Привязка ObservableCollection к ListView в .NET MAUI и C#

Пример в xaml

Аналогичный пример в xaml. В коде страницы 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">
        <StackLayout Orientation="Vertical">
            <Entry x:Name="nameEntry" Margin="5" Placeholder = "Enter name" />
            <Entry x:Name="ageEntry" Margin="5" Placeholder = "Enter age" />
            <Button Clicked="SaveButton_Clicked" Text="Save" WidthRequest="100" HorizontalOptions="Start" />
        </StackLayout>
        <ListView ItemsSource="{Binding Users}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <ViewCell.View>
                            <StackLayout>
                                <Label Text="{Binding Name}" FontAttributes="Bold" />
                                <Label Text="{Binding Age}" />
                            </StackLayout>
                        </ViewCell.View>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

В файл кода MainPage.xaml.cs добавим к странице обработчики кнопок и привязку к списку :

using System.Collections.ObjectModel;

namespace HelloApp;

public partial class MainPage : ContentPage
{
    public ObservableCollection<User> Users { get; set; }
    public MainPage()
	{
		InitializeComponent();
        Users = new ObservableCollection<User>
        //Users = new List<User>
        {
            new User {Name="Tom", Age=38 },
            new User {Name = "Bob", Age = 42}
        };
        BindingContext = this; // привязка к текущему объекту
    }
    private void SaveButton_Clicked(object sender, EventArgs e)
    {
        int.TryParse(ageEntry.Text, out var age);
        Users.Add(new User { Name = nameEntry.Text, Age = age });
        nameEntry.Text = ageEntry.Text = "";
    }
}
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850