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

Xamarin中如何用API返回的JSON更新ObservableCollection并刷新ListView?

Xamarin ListView 接受任务后无法自动更新的解决方案

问题场景

Xamarin移动端应用包含3个嵌套在Frame内的ListView,首次打开时任务列表显示正常;但接受任务后,该任务应转移至「待办列表」,此时所有列表均无法自动同步最新数据。

核心问题分析

  1. 集合更新逻辑错误:原代码先清空现有集合,却未将处理后的任务添加回集合,直接替换ObservableCollection的方式可能导致绑定失效
  2. 数据处理与UI线程耦合:日期转换等耗时操作在UI线程执行,可能阻塞更新
  3. 任务接受后未触发刷新:缺少接受任务完成后主动调用列表刷新的逻辑
  4. 任务实体未实现属性变更通知:若任务属性(如状态)变化,UI无法感知

修复步骤

1. 修复集合更新逻辑

修改obtenerTareas方法,优先更新现有ObservableCollection而非直接替换,利用其CollectionChanged事件确保ListView自动更新:

public async Task obtenerTareas(string idAgente)
{
    try
    {
        string apiUrl = $"https://tareas.sistemaonline.com.ar/rest-api/AgentesRetails?agenteRetailGET={idAgente}";
        using HttpClient client = new HttpClient();
        HttpResponseMessage response = await client.GetAsync(apiUrl);

        if (response.IsSuccessStatusCode)
        {
            string jsonContent = await response.Content.ReadAsStringAsync();
            ObservableCollection<Tarea> tareas = JsonConvert.DeserializeObject<ObservableCollection<Tarea>>(jsonContent);
            
            // 后台处理日期数据,避免阻塞UI线程
            foreach (var tarea in tareas)
            {
                DateTime fecha = Convert.ToDateTime(tarea.fecha_sol);
                tarea.mes = fecha.ToString("MMMM").Substring(0, 3).ToUpper();
                tarea.dia = $"  {fecha:dd}  ";
            }

            Device.BeginInvokeOnMainThread(() =>
            {
                // 清空现有集合并添加新数据,触发CollectionChanged事件
                Lista.Clear();
                foreach (var tarea in tareas)
                {
                    Lista.Add(tarea);
                }
            });
        }
        else
        {
            await App.Current.MainPage.DisplayAlert($"加载任务失败 {response.StatusCode}", "确定", "确定");
        }
    }
    catch (Exception ex)
    {
        await App.Current.MainPage.DisplayAlert($"错误 {ex.Message}", "确定", "确定");
    }
}

注:对obtenerTareasP和obtenerTareasC方法执行相同修改,确保待办列表、进行中列表的更新逻辑一致。

2. 为Tarea实体实现INotifyPropertyChanged

确保任务属性变化时UI能同步更新,修改Tarea类:

public class Tarea : INotifyPropertyChanged
{
    private string _mes;
    public string mes
    {
        get => _mes;
        set
        {
            if (_mes != value)
            {
                _mes = value;
                OnPropertyChanged(nameof(mes));
            }
        }
    }

    private string _dia;
    public string dia
    {
        get => _dia;
        set
        {
            if (_dia != value)
            {
                _dia = value;
                OnPropertyChanged(nameof(dia));
            }
        }
    }

    private DateTime _fecha_sol;
    public DateTime fecha_sol
    {
        get => _fecha_sol;
        set
        {
            if (_fecha_sol != value)
            {
                _fecha_sol = value;
                OnPropertyChanged(nameof(fecha_sol));
            }
        }
    }

    // 添加其他任务属性的变更通知逻辑,如任务状态、ID等

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

3. 任务接受后触发列表刷新

在接受任务的API调用完成后,主动调用刷新命令更新所有列表:

// 在ViewModel中添加接受任务的命令
public ICommand AceptarTareaCommand => new Command(async (tareaId) =>
{
    try
    {
        string apiUrl = $"https://tareas.sistemaonline.com.ar/rest-api/AceptarTarea?tareaId={tareaId}";
        using HttpClient client = new HttpClient();
        HttpResponseMessage response = await client.PostAsync(apiUrl, null);
        
        if (response.IsSuccessStatusCode)
        {
            // 接受成功后立即刷新所有任务列表
            RefrescarCommand.Execute(null);
        }
        else
        {
            await App.Current.MainPage.DisplayAlert("接受任务失败", "请重试", "确定");
        }
    }
    catch (Exception ex)
    {
        await App.Current.MainPage.DisplayAlert($"错误 {ex.Message}", "确定", "确定");
    }
});

4. 完善ListView下拉刷新绑定(可选)

若需支持下拉刷新,确保XAML中绑定正确:

<ListView ItemsSource="{Binding Lista}" 
          HasUnevenRows="True"
          IsRefreshing="{Binding EsRefrescando}"
          RefreshCommand="{Binding RefrescarCommand}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <!-- 任务项UI模板 -->
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

验证方案

  1. 接受任务后,确认API返回成功
  2. 检查三个ListView是否同步更新:原任务从「可用列表」移除,出现在「待办列表」
  3. 测试下拉刷新功能,确认列表能重新加载最新数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 16:59:54