Using [NotifyPropertyChangedFor()] source generator on ObservableCollection is not updating UI

201 views Asked by At

I would expect something like this to work:

[ObservableProperty]
[NotifyPropertyChangedFor(nameof(Count))]
public ObservableCollection<TODO> todos = new();

public int Count => Todos.Count;

While the Count is getting updated at the ViewModel layer, the UI does not seem to update. I have also tried using the OnTodosChanged method generated by the Mvvm CommunityToolkit source generator but that is not getting fired as well. Note that I am expected the UI to update on invoking the Add, etc methods of Todos.

  1. Why doesn't [NotifyPropertyChangedFor(nameof(Count))] update the UI Count on Adding to Todos collection? If this is not the way to do this, then what is?
  2. Why doesn't OnTodosChanged get called on Addition of elements to Todos collection?
  3. Would the UI update for an operation like Todos[0].IsCompleted = true? If not, what is the way to handle this?

The reason I decided to post here was I could not find any relevant documentation (which is quite frustrating because I am thinking this might be something that is commonly done) nor any tutorial videos / sample apps leading me to question if this is the correct way to go about this. Help would be appreciated! - Thank you :^)

1

There are 1 answers

5
Julian On BEST ANSWER

What you're doing with the MVVM Source Generators here:

[ObservableProperty]
[NotifyPropertyChangedFor(nameof(Count))]
public ObservableCollection<TODO> todos = new();

public int Count => Todos.Count;

is equivalent to writing the following:

private ObservableCollection<TODO> _todos = new();
public ObservableCollection<TODO> Todos
{
    get => _todos;
    set
    {
        if(_todos == value) return;
        _todos = value;
        OnPropertyChanged(nameof(Todos));
        OnPropertyChanged(nameof(Count));
    }
}

public int Count => Todos.Count;

The PropertyChanged notification only occurs when the Todos property is changed, but not when the content of the ObservableCollection<TODOS> changes. Adding elements to the collection is not changing the property.

If you want to notify changes to the Count property when items are added to the Todos collection, then you need to subscribe to the collections's CollectionChanged event:

[ObservableProperty]
public ObservableCollection<TODO> todos;

public int Count => Todos.Count;

public YouClassConstructor()
{
    Todos = new();
    Todos.CollectionChanged += (s,e) => OnPropertyChanged(nameof(Count));
}

I've also written a small blog series about the MVVM Source Generators, if you want to take a deeper dive into the topic.