Reputation: 3070
I have a bindable StackLayout
bound to a List
in the ViewModel
. When a button is pressed I am adding an element to the list and then invoking PropertyChanged
with the name of the list.
I don't understand why the UI does not get updated in this case. I know that I should use an ObservableCollection
, and I know how to do it, but I am curious about why the UI does not change if I am invoking PropertyChanged
myself.
This is the ViewModel and Model class:
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"));
}
}
And this is the view:
<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>
Upvotes: 2
Views: 938
Reputation: 18861
If we check the source code of ObservableCollection , we will see that it had implemented INotifyCollectionChanged and INotifyPropertyChanged in default while List didn't .
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
If a list will contain the same items for their whole lifetime, but the individual objects within that list will change, then it's enough for just the objects to raise change notifications (typically through INotifyPropertyChanged) and List is sufficient. But if the list will contain different objects from time to time, or if the order changes, then you should use ObservableCollection.
That is why we always suggest users to choose ObservableCollection instead of List .
Upvotes: 2