You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin.Forms CollectionView选中项progress属性UI更新不一致问题

问题原因

  • 代码内混用大小写的currentEntry和CurrentEntry变量,若二者指向不同实例,修改CurrentEntry的属性不会同步到列表绑定的实例,自然不会触发UI更新。
  • 多余的Task.Run包裹异步逻辑导致线程上下文切换,增加了属性更新通知的线程同步风险,部分情况下UI线程无法正确接收INotifyPropertyChanged的触发事件。
  • 属性更新未显式调度到UI线程执行,后台线程触发的属性变更在部分场景下会丢失通知。

修复方案

  1. 移除多余的Task.Run包裹,异步IO请求本身无需额外开启后台线程。
  2. 统一所有地方使用大写的CurrentEntry变量,确保修改的就是选中项绑定的实例。
  3. 显式将progress属性的更新逻辑调度到UI线程执行。

修复后的业务逻辑代码

async Task Info()
{
    IsBusy = true;
    try
    {
        if (CurrentEntry.progress < CurrentEntry.media.Episodes)
        {
            string token = Preferences.Get("token", "default_value");
            var anilistGraphQlHttpClient = new GraphQLHttpClient("https://graphql.anilist.co", new NewtonsoftJsonSerializer());
            anilistGraphQlHttpClient.HttpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);

            var IncreaseProgressEntry = new GraphQLRequest
            {
                Query = @"mutation IncreaseProgress($id: Int, $progress: Int) {   SaveMediaListEntry(id: $id, progress: $progress) {     id     progress     status   } } ",
                OperationName = "IncreaseProgress",
                Variables = new
                {
                    id = CurrentEntry.id,
                    progress = CurrentEntry.progress + 1
                }
            };
            await anilistGraphQlHttpClient.SendQueryAsync<Data>(IncreaseProgressEntry);

            // 显式在UI线程更新属性
            MainThread.BeginInvokeOnMainThread(() =>
            {
                CurrentEntry.progress += 1;
            });
            Console.WriteLine("success");
        }
    }
    catch (HttpRequestException httpRequestException)
    {
        Console.WriteLine(httpRequestException);
        MainThread.BeginInvokeOnMainThread(() =>
        {
            DependencyService.Get<Toast>().Show("无网络连接");
        });
    }
    catch (GraphQLHttpRequestException e)
    {
        Console.WriteLine(e);
        Preferences.Set("token", "default_value");
        await Shell.Current.GoToAsync("//LandingPage");
        MainThread.BeginInvokeOnMainThread(() =>
        {
            DependencyService.Get<Toast>().Show("令牌已过期或被撤销");
        });
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
        MainThread.BeginInvokeOnMainThread(() =>
        {
            DependencyService.Get<Toast>().Show("发生未知错误");
        });
    }
    finally
    {
        IsBusy = false;
    }
}

额外检查项

  • 确认绑定到CollectionView的AnimeGroupObservable内存储的ListEntry实例,和CurrentEntry选中的是同一个引用,刷新列表时不要直接替换整个列表实例,优先更新现有实例的属性。
  • 可在ListEntry的progress属性set方法内加断点,确认每次点击+号都会触发OnPropertyChanged调用,若未触发则说明修改的不是同一个实例。

内容的提问来源于stack exchange,提问作者ziomek64

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 08:39:01