简体   繁体   English

使用 CommunityToolkit.Mvvm 在 ObservableProperty 更改时调用方法

[英]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.我正在我的 .NET MAUI 应用程序中实现自动完成功能,并且在我的视图 model 中使用CommunityToolkit.Mvvm代码生成器来处理可观察的属性。

I have the following code and I'm trying call GetSuggestions() method when the SearchText changes.我有以下代码,我正在尝试在SearchText更改时调用GetSuggestions()方法。

[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. [NotifyCanExecuteChangedFor] 的目标必须是可访问的 IRelayCommand 属性,但“GetSuggestions”在类型 MyViewModel 中没有匹配项。

What am I doing wrong here?我在这里做错了什么?

I guess there are two problems here.我想这里有两个问题。

Why is this error occurring?为什么会出现这个错误?

That happens because GetSuggestions is not a Command.发生这种情况是因为GetSuggestions不是命令。 Try adding the [RelayCommand] attribute to your method.尝试将[RelayCommand]属性添加到您的方法中。

[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.然后将NotifyCanExecuteChangedFor链接到自动生成的命令。

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

The second one.第二个。

You need to你需要

call GetSuggestions() method when the SearchText changes. SearchText 更改时调用 GetSuggestions() 方法。

The NotifyCanExecuteChangedFor attribute doesn't do that. NotifyCanExecuteChangedFor属性不这样做。

In the autogenerated source code you should find an empty partial method called OnSearchTextPropertyChanged .在自动生成的源代码中,您应该找到一个名为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.如果这是您要搜索的内容, GetSuggestions不需要使用RelayCommand属性进行标记。

Only meant as more of an amendment of @RMinato's answer.仅意味着对@RMinato 的回答的更多修正。

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(); ".正如我的评论所说:“虽然其中大部分内容都有帮助,但我需要做一些不同的事情,包括使用[RelayCommand]并将我的OnPropChanged方法中的方法调用为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;
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C# CommunityToolkit.Mvvm ObservableProperty 列表 - C# CommunityToolkit.Mvvm ObservableProperty on a list 如何使用 CommunityToolkit.Mvvm 调用事件 - How to call events using CommunityToolkit.Mvvm 使用 CommunityToolkit.Mvvm 通知 CanExecuteChanged 的 RelayCommand 时出现 StackOverflow 异常 - StackOverflow Exception when notifying RelayCommand of CanExecuteChanged using CommunityToolkit.Mvvm WinUI 3 CommunityToolkit Datagrid 在使用 CommunityToolkit.Mvvm 时显示来自两个模型的数据 - WinUI 3 CommunityToolkit Datagrid displaying data from two models while using CommunityToolkit.Mvvm 使用 CommunityToolkit.Mvvm 处理可观察对象属性 - Handling observable object properties with CommunityToolkit.Mvvm 如何在 C# 中使用 Community - How do I bind an object that is periodically modified to a treeview in C# WPF using the CommunityToolkit.MVVM? 显示 ObservableGroupedCollection 的正确方法<string, telement>使用 Wpf .NET 6 和 CommunityToolkit.Mvvm 包</string,> - Proper way of displaying an ObservableGroupedCollection<string, TElement> using Wpf .NET 6 and the CommunityToolkit.Mvvm Package 无法在使用 CommunityToolkit.Mvvm 的视图模型中使用 ICommand 属性 - Can't use ICommand attribute in view model using CommunityToolkit.Mvvm CommunityToolkit.MVVM 命名空间“命名空间”已包含“类型”的定义 - CommunityToolkit.MVVM The namespace 'namespace' already contains a definition for 'type' 使用 CommunityToolkit.Mvvm 和依赖注入更新视图模型的属性 - Update Properties across Viewmodels with CommunityToolkit.Mvvm and Dependency Injection
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM