Sam
Sam

Reputation: 30298

Set ObservableCollection as ObservableProperty

I'm switching to CommunityToolkit.Mvvm source generators to handle my view models and I'm a bit confused about how to handle ObservableCollections.

My view model looks like this:

public partial class MyViewModel : ObservableObject
{
   [ObservableProperty]
   string name;

   [ObservableProperty]
   ObservableCollection<MyModel> data;

   async Task Init()
   {
      // Fetch data from API
      var response = await _api.GetData();

      if(response.IsSuccessful)
      {
           Name = response.Name;
           Data = new ObservableCollection<MyModel>(response.Data);
      }
   }
}

This doesn't seem to assign my data to the Name and Data properties. I think I'm supposed to assign to public properties i.e. Name and Data and NOT name and data. Am I right about that?

What am I doing wrong here? Do we use [ObservableProperty] with ObservableCollection also? I'm missing something here but not sure what.

Upvotes: 1

Views: 2259

Answers (1)

Sam
Sam

Reputation: 30298

Here are the answers:

  1. As @GeraldVersluis mentioned in the comments, we cannot create a new instance of the ObservableCollection during data assignment as it breaks the data binding.
  2. We do NOT use [ObservableProperty] with ObservableCollection's as they automatically call NotifyPropertyChanged. Furthermore, quoting Brandon Minnick, ObservableCollection should always be a public read-only property, initialized using = new()
  3. We assign our data to public properties
  4. We need to use this to reference the property
  5. Also, notice that I added new(); to data to make sure it's instantiated and is not null

Final code looks like this:

public partial class MyViewModel : ObservableObject
{
   [ObservableProperty]
   string name;

   ObservableCollection<MyModel> Data { get; } = new();

   async Task Init()
   {
      // Fetch data from API
      var response = await _api.GetData();

      if(response.IsSuccessful)
      {
           this.Name = response.Name;

           foreach(var item in response.Data)
              this.Data.Add(item);
      }
   }
}

Upvotes: 4

Related Questions