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?
I guess there are two problems here.
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;
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.
Only meant as more of an amendment of @RMinato's answer.
As my comment say: "While most of this was helpful, I need to do a few things different including using the [RelayCommand]
and calling the method inside my OnPropChanged
method to be Task.Run(() => this.MyMethodAsync()).Wait();
".
My code looks like:
[QueryProperty(nameof(Course), nameof(Course))]
public partial class CourseDetailViewModel : BaseViewModel
{
private readonly CourseService courseService;
public CourseDetailViewModel(CourseService courseService)
{
this.courseService = courseService;
}
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(GetCourseDetailCommand))]
Course course;
partial void OnCourseChanged(Course value)
{
Task.Run(() => this.GetCourseDetailAsync()).Wait();
}
[RelayCommand]
public async Task GetCourseDetailAsync()
{
if (GetCourseDetailCommand.IsRunning) return;
try
{
IsBusy = true;
course = await courseService.GetCourseDetailAsync(course.Id);
}
catch (Exception ex)
{
Debug.WriteLine($"Failed to get course detail. Error: {ex.Message}");
await Shell.Current.DisplayAlert("Error!",
$"Failed to get course detail: {ex.Message}", "OK");
throw;
}
finally
{
IsBusy = false;
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.