ListView не обновляется

У меня есть товарная корзина. Я хотел бы показать CartItems в виде списка с ItemName и количеством. Когда я нажимаю кнопку, количество элементов в listView должно увеличиваться.

Моя проблема: CartItem наблюдаемой коллекции увеличивается каждый раз, когда я правильно нажимаю кнопку, но пользовательский интерфейс не обновляется/не обновляется. Есть кто-нибудь, кто может мне помочь??

Вот код:

public class AboutViewModel : BaseViewModel
{
    public AboutViewModel()
    {
        AddCartItem = new Command(AddItem);
    
        cartItems = new ObservableCollection<CartItem>();
        cartItems.Add(new CartItem { ItemName = "Item1", Quantity = 4 });
        cartItems.Add(new CartItem { ItemName = "Item2", Quantity = 2 });
    }

    public ICommand AddCartItem { get; }
    
    public ObservableCollection<CartItem> cartItems;
    public ObservableCollection<CartItem> CartItems
    {
        get { return cartItems; }
        set
        {
            cartItems = value;
                    
            OnPropertyChanged("CartItems");
        }
    }

    void AddItem()
    {
        cartItems[0].Quantity++;
        CartItems = cartItems;
    }
}
<StackLayout>
    <ListView ItemsSource = "{Binding CartItems">
        <ListView.ItemTemplate>
            <DataTemplate>
                <TextCell Text = "{Binding ItemName, Mode=TwoWay}"
                          Detail = "{Binding Quantity, Mode=TwoWay}"></TextCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
<StackLayout>
                
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height = "*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width = "*"/>
        </Grid.ColumnDefinitions>
    
        <BoxView
            Color = "Blue" />
        <Button Text = "Add Name" Command = "{Binding AddCartItem}"/>

AddItem должен добавить новый элемент в список или увеличить количество существующего элемента? Если предполагается увеличить количество, как узнать, какой элемент увеличить?

Jason 26.12.2022 21:47

Вы обновляете значение первой записи в cartItems вспомогательном поле типа ObservableCollection (которое в идеале должно быть private BTW), а затем вы по какой-то причине обновляете ссылку общедоступного CartItems свойства, что не обязательно. В этом случае ваш пользовательский интерфейс будет обновляться только в том случае, если какой-либо из элементов внутри коллекции действительно вызывает событие PropertyChanged. Можете ли вы показать, где и как определяется класс CartItem?

ewerspej 26.12.2022 22:14

Вместо этого используйте CollectionView, он имеет лучшую производительность и восприимчив к изменениям.

FabriBertani 27.12.2022 02:54
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы хотите обновить пользовательский интерфейс после изменения значения свойства Quantity в модели CartItem , вам необходимо реализовать интерфейс INotifyPropertyChanged для CartItem.

Основываясь на вашем коде, я выполнил эту функцию, вы можете обратиться к следующему коду:

CartItem.cs

public class CartItem: INotifyPropertyChanged 
    {
        public string ItemName { get; set; }

        //public int Quantity { get; set; }
        int _quantity;
        public int Quantity
        {
            get => _quantity;
            set => SetProperty(ref _quantity, value);
        }

        bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
        {
            if (Object.Equals(storage, value))
                return false;

            storage = value;
            OnPropertyChanged(propertyName);
            return true;
        }

        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

Овиевмодел.cs

public class AboutViewModel 
    {
        public AboutViewModel()
        {
            AddCartItem = new Command(AddItem);

            CartItems = new ObservableCollection<CartItem>();
            CartItems.Add(new CartItem { ItemName = "Item1", Quantity = 4 });
            CartItems.Add(new CartItem { ItemName = "Item2", Quantity = 2 });
        }
        public ICommand AddCartItem { get; }

        public ObservableCollection<CartItem> CartItems { get; set; }

        void AddItem()
        {
            CartItems[0].Quantity++;
        }
    }

MainPage.xaml

<?xml version = "1.0" encoding = "utf-8" ?> 
<ContentPage xmlns = "http://xamarin.com/schemas/2014/forms"
             xmlns:x = "http://schemas.microsoft.com/winfx/2009/xaml" xmlns:listviewapp = "clr-namespace:ListViewApp"
             x:Class = "ListViewApp.MainPage">

    <ContentPage.BindingContext>
        <listviewapp:AboutViewModel></listviewapp:AboutViewModel>
    </ContentPage.BindingContext>

    <StackLayout>
        <ListView ItemsSource = "{Binding CartItems}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextCell Text = "{Binding ItemName, Mode=TwoWay}"
                              Detail = "{Binding Quantity, Mode=TwoWay}"></TextCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

        <Button Text = "Add Name" Command = "{Binding AddCartItem}"/>
    </StackLayout>

</ContentPage>

Примечание:

1. На самом деле вам вообще не нужно определять другую переменную cartItems. Вы можете определить только переменную CartItems:

public ObservableCollection<CartItem> CartItems { get; set; }

2. Для документа Класс ObservableCollection мы знаем, что этот класс:

Представляет коллекцию динамических данных, которая предоставляет уведомления, когда элементы добавляются или удаляются, или когда весь список обновляется.

Таким образом, если вы добавите модификаторы public ObservableCollection<CartItem> для переменной CartItems, при добавлении или удалении одного или нескольких элементов в этот список пользовательский интерфейс будет обновляться. И если вы хотите, чтобы пользовательский интерфейс обновлялся автоматически после изменения значения свойства Quantity в модели CartItem , вам необходимо реализовать интерфейс INotifyPropertyChanged для CartItem.

public ObservableCollection<CartItem> CartItems { get; set; }

Другие вопросы по теме