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

ListView在OnAppearing调用WebService时无法刷新的问题求助

解决ListView在PopAsync/DatePicker更新后不刷新的问题

嘿,我仔细看了你的代码和问题描述,发现有两个关键坑导致了ListView不更新的情况,咱们一步步来搞定它:

1. 视图后台的ViewModel实例完全不匹配!

你看你的视图后台代码:

// 这里单独创建了一个ViewModel实例
SuccesViewModel SuccesViewModel = new SuccesViewModel();
public Online_Succes() {
    InitializeComponent();
    // 这里又new了另一个ViewModel,还给BindingContext赋值了
    BindingContext = new SuccesViewModel();
}
protected override void OnAppearing() {
    // 你调用的是第一个实例的FillSuccess,但视图绑定的是第二个啊!
    SuccesViewModel.FillSuccess();
    base.OnAppearing();
}

这俩是完全独立的对象!你在OnAppearing里更新的那个ViewModel根本没和视图绑定,所以不管你怎么改SuccesList,视图都不会有反应。

修复方法:把ViewModel实例统一起来:

private SuccesViewModel _succesViewModel;
public Online_Succes() {
    InitializeComponent();
    _succesViewModel = new SuccesViewModel();
    BindingContext = _succesViewModel;
}
protected override void OnAppearing() {
    _succesViewModel.FillSuccess();
    base.OnAppearing();
}

2. ViewModel没实现INotifyPropertyChanged,集合替换时视图收不到通知

你的SuccesList看起来是直接赋值的字段,每次FillSuccess都new一个新的ObservableCollection,但视图根本不知道你换了新集合——因为没有属性变更通知。

修复ViewModel:先让ViewModel实现属性变更通知接口,再把SuccesList改成带通知的属性:

public class SuccesViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private ObservableCollection<Succes> _succesList;
    public ObservableCollection<Succes> SuccesList
    {
        get => _succesList;
        set
        {
            _succesList = value;
            OnPropertyChanged(nameof(SuccesList));
        }
    }

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

    public SuccesViewModel() 
    { 
        SuccesList = new ObservableCollection<Succes>();
        FillSuccess(); 
    }
    
    public void FillSuccess() {
        SuccesList.Clear(); // 清空现有集合,不用每次new新的
        var date = App.Date;
        BasicHttpBinding binding = CreateBasicHttp();
        this.client1 = new BienEtreServiceClient(binding, EndPoint);
        this.instance = ((IBienEtreService)client1.InnerChannel);
        // 注意:避免重复订阅事件,先取消再订阅
        client1.GetSuccesCompleted -= ClientOnGetSuccesCompleted;
        client1.GetSuccesCompleted += ClientOnGetSuccesCompleted;
        client1.GetSuccesAsync(App.UserID, date);
    }

    private void ClientOnGetSuccesCompleted(object sender, GetSuccesCompletedEventArgs e) {
        SuccesList.Clear();
        foreach (Succes item in e.Result) {
            if (item.Date.ToString("yyyy-MM-dd") == App.Date.ToString("yyyy-MM-dd")) {
                SuccesList.Add(item);
            }
        }
    }
}

这里的关键细节:

  • 复用现有ObservableCollection,而不是每次创建新的(ObservableCollection本身会触发CollectionChanged通知视图更新)
  • 给SuccesList属性加上变更通知,确保万一需要替换集合时视图能感知
  • 每次订阅异步回调前先取消订阅,避免多次调用FillSuccess导致回调执行多次

3. DatePicker更新后的处理

对于DatePicker的场景,你只需要在日期选择事件里调用绑定的ViewModel的FillSuccess就行:

private void DatePicker_DateSelected(object sender, DateChangedEventArgs e) {
    App.Date = e.NewDate;
    ((SuccesViewModel)BindingContext).FillSuccess();
}

总结

你的核心问题就是ViewModel实例不匹配+缺少属性变更通知,按照上面的步骤改完后,不管是从添加页面PopAsync回来,还是用DatePicker切换日期,ListView都能正常刷新数据了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:11:51