Search code examples
c#observablecollectioncommunity-toolkit-mvvm

Call method when ObservableProperty changes using CommunityToolkit.Mvvm


I'm implementing auto complete feature in my .NET MAUI app and I'm using CommunityToolkit.Mvvm code generators in my view model to handle observable properties.

I have the following code and I'm trying call GetSuggestions() method when the SearchText changes.

[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(GetSuggestions))]
string searchText;

[ObservableProperty]
bool showSuggestions;

ObservableCollection<string> Suggestions { get; } = new();

private async Task GetSuggestions()
{
   if(string.IsNullOrEmpty(SearchText) || SearchText.Length < 3)
      return;

   var data = await _myApiService.GetSuggestions(SearchText.Trim());
   if(data != null && data.Count > 0)
   {
      Suggestions.Clear();
      foreach(var item in data)
         Suggestions.Add(item);

      ShowSuggestions = true;
   }
}

This is giving me the following error:

The target(s) of [NotifyCanExecuteChangedFor] must be an accessible IRelayCommand property, but "GetSuggestions" has no matches in type MyViewModel.

What am I doing wrong here?


Solution

  • I guess there are two problems here.

    Why is this error occurring?

    That happens because GetSuggestions is not a Command. Try adding the [RelayCommand] attribute to your method.

    [RelayCommand]
    private async Task GetSuggestions()
    {
        if(string.IsNullOrEmpty(SearchText) || SearchText.Length < 3)
           return;
    
        var data = await _myApiService.GetSuggestions(SearchText.Trim());
        if(data != null && data.Count > 0)
        {
            Suggestions.Clear();
            foreach(var item in data)
            Suggestions.Add(item);
    
            ShowSuggestions = true;
        }
    }
    

    Then link NotifyCanExecuteChangedFor to the autogenerated command.

    [ObservableProperty]
    [NotifyCanExecuteChangedFor(nameof(GetSuggestionsCommand))]
    string searchText;
    

    The second one.

    You need to

    call GetSuggestions() method when the SearchText changes.

    The NotifyCanExecuteChangedFor attribute doesn't do that.

    In the autogenerated source code you should find an empty partial method called OnSearchTextPropertyChanged. Try implementing it.

    partial void OnSearchTextPropertyChanged(string value)
    {
        GetSuggestions();
    }
    

    If this is what you're searching for, GetSuggestions doesn't need to be marked with the RelayCommand attribute.