Reputation: 30324
I went through SO questions on this topic and thought I followed the examples carefully but I still don't see a UI update when a property of an item in a CollectionView
gets updated.
First, I made sure the property in my model is decorated with ObservableProperty
:
public partial class Student : ObservableObject
{
public int Id { get; set; }
public string Name { get; set; }
[ObservableProperty]
bool isRegistered;
}
I then use an ObservableCollection
in my view model which is also decorated with ObservableProperty
:
public partial class MyViewModel : ObservableObject
{
public MyViewModel()
{
var student = new Student
{
Id = 123,
Name = "John Doe",
IsRegistered = false
};
Students.Add(student);
student = new Student
{
Id = 234,
Name = "Jane Doe",
IsRegistered = false
};
Students.Add(student);
}
[ObservableProperty]
ObservableCollection<Student> students = new();
[RelayCommand]
void UpdateRegistrations()
{
foreach(var item in Students)
item.IsRegistered = true;
}
}
Here's the XAML:
<ContentPage...>
<Grid
RowDefinitions="*,50">
<CollectionView
Grid.Row="0"
ItemsSource="{Binding Students}">
<CollectionView.ItemTemplate>
<DataTemplate
x:DataType="model:Student">
<Grid
ColumnDefinitions="*,30">
<Label
Grid.Column="0"
Text="{Binding Name}" />
<Image
Grid.Column="1"
Source="checkmark.png"
IsVisible="{Binding IsRegistered}" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Button
Grid.Row="1"
Text="Update Data"
Command="{Binding UpdateRegistrationsCommand}" />
</Grid>
</ContentPage>
I don't see the change in IsRegistered
reflected in the UI after executing UpdateRegistrations()
. What am I missing here? I'm under the impression that CommunityToolkit.Mvvm handles INotifyPropertyChanged
logic. Do I need to handle the change manually?
Upvotes: 3
Views: 3056
Reputation: 15400
ObservableCollection
doesn't need the [ObservableProperty]
attribute; it automatically invokes NotifyPropertyChanged
and NotifyCollectionChanged
when you call its methods like .Add()
. That's kinda the whole reason we use ObservableCollection<T>
instead of List<T>
for MVVM.
In .NET MAUI (and Xamarin), View Model properties used for bindings must be a public non-static property, so we'll promote Students
from a field to a read-only property (aka add { get; }
).
In the XAML, the DataTemplate
bindings are using incorrect syntax: the Name
binding is missing the Binding
keyword, and both should be wrapped in double-quotes ("
). These bugs should be invoking a compiler (syntax) error when XAMLC
is enabled, so make sure you haven't accidentally disabled XAMLC
.
public partial class MyViewModel : ObservableObject
{
public MyViewModel()
{
Students.Add(new Student
{
Id = 123,
Name = "John Doe",
IsRegistered = false
});
Students.Add(new Student
{
Id = 234,
Name = "Jane Doe",
IsRegistered = false
});
}
public ObservableCollection<Student> Students { get; } = new();
[RelayCommand]
void UpdateRegistrations()
{
foreach(var item in Students)
item.IsRegistered = true;
}
}
<ContentPage...>
<Grid
RowDefinitions="*,50">
<CollectionView
Grid.Row="0"
ItemsSource="{Binding Students}">
<CollectionView.ItemTemplate>
<DataTemplate
x:DataType="model:Student">
<Grid
ColumnDefinitions="*,30">
<Label
Grid.Column="0"
Text="{Binding Name}" />
<Image
Grid.Column="1"
Source="checkmark.png"
IsVisible="{Binding IsRegistered}" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Button
Grid.Row="1"
Text="Update Data"
Command="{Binding UpdateRegistrationsCommand}" />
</Grid>
</ContentPage>
Upvotes: 4