Обновленный список не изменяется в пользовательском интерфейсе при вызове PropertyChanged в Xamarin.Forms - PullRequest
2 голосов
/ 03 августа 2020

У меня есть привязка StackLayout к List в ViewModel. При нажатии кнопки я добавляю элемент в список, а затем вызываю PropertyChanged с именем списка.

Я не понимаю, почему пользовательский интерфейс не обновляется в этом случае. Я знаю, что мне следует использовать ObservableCollection, и я знаю, как это сделать, но мне любопытно, почему пользовательский интерфейс не меняется, если я сам вызываю PropertyChanged.

Это ViewModel и Класс модели:

    public class Element
    {
        public string Value { get; set; }
    }

    public class MainViewModel : INotifyPropertyChanged
    {
        public List<Element> Elements { get; set; }
        public ICommand AddElementCommand { get; private set; }

        public event PropertyChangedEventHandler PropertyChanged;

        public MainViewModel()
        {
            AddElementCommand = new Command(AddElement);

            Elements = new List<Element>();
            Elements.Add(new Element { Value = "test1" });
        }

        void AddElement()
        {
            Elements.Add(new Element { Value = "testAgain" });
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Elements"));
        }
    }

А это вид:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="TestList.MainPage"
             x:Name="page">
    <StackLayout>
        <StackLayout Orientation="Horizontal">
            <Label Text="Elements"
                       FontSize="Large"
                       HorizontalOptions="FillAndExpand"
                       VerticalOptions="Center"/>
            <Button Command="{Binding AddElementCommand}"
                    Text="+" FontSize="Title"
                        VerticalOptions="Center"/>
        </StackLayout>
        <StackLayout BindableLayout.ItemsSource="{Binding Elements}">
            <BindableLayout.ItemTemplate>
                <DataTemplate>
                      <Entry Text="{Binding Value, Mode=TwoWay}" HorizontalOptions="FillAndExpand"/>
                </DataTemplate>
            </BindableLayout.ItemTemplate>
        </StackLayout>
    </StackLayout>
</ContentPage>

1 Ответ

1 голос
/ 03 августа 2020

Если мы проверим исходный код ObservableCollection , мы увидим, что он реализовал INotifyCollectionChanged и INotifyPropertyChanged по умолчанию, а List не сделал.

public class ObservableCollection<T> : Collection<T>, INotifyCollectionChanged, INotifyPropertyChanged
public class List<T> : ICollection<T>, IEnumerable<T>, IEnumerable, IList<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection, IList

Если список будет содержать одни и те же элементы на протяжении всего их срока службы, но отдельные объекты в этом списке будут меняться, тогда достаточно, чтобы только объекты вызывали уведомления об изменениях (обычно через INotifyPropertyChanged ) и List достаточно. Но если список будет время от времени содержать разные объекты, или если порядок меняется, то вам следует использовать ObservableCollection .

Поэтому мы всегда предлагаем пользователям выбирать ObservableCollection вместо Список .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...