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

FlowListView结合ObservableCollection定时更新UI失效问题求助

解决思路与代码修复

我来帮你分析下问题所在,你遇到的UI不刷新问题主要有几个核心原因,咱们一步步来解决:


核心问题拆解

  1. 后台线程操作UI导致更新失效
    Device.StartTimer的回调本身就是在UI线程执行的,你额外用Task.Run把InitAsync丢到后台线程,这会导致后续更新集合/UI的操作不在主线程,Xamarin.Forms不允许后台线程直接修改UI相关的内容,自然就同步失败了。

  2. FlowItemsSource绑定了非可观察集合
    你把_items.Items.Where(...).ToList()赋值给FlowItemsSource,ToList()会把ObservableCollection转换成普通List——而普通List没有INotifyCollectionChanged接口,就算原ObservableCollection内容变了,这个List也不会通知UI刷新。

  3. 重新实例化Flashlist导致绑定引用断裂
    每次InitAsync里你都new了一个新的Flashlist对象,原来和UI绑定的旧引用就失效了,哪怕新集合有数据变化,UI也感知不到。


修改后的代码示例

1. 调整OnAppearing中的Timer逻辑

去掉多余的Task.Run,直接在Timer回调里执行异步方法:

protected async override void OnAppearing() {
    MakeWebRequest();
    if (IsConnected) {//10 Seconds for Testing
        Device.StartTimer(TimeSpan.FromSeconds(10), async () => {
            await InitAsync();
            return true;
        });
    } else {
        await Navigation.PushAsync(new ErrorView());
    }
}

2. 重构Flashlist类,保持集合引用稳定

不要重新赋值Items属性,直接初始化一个固定引用的ObservableCollection:

public class Flashlist : INotifyPropertyChanged {
    // 固定引用的ObservableCollection,避免重新赋值导致绑定断裂
    public ObservableCollection<Product> Items { get; } = new ObservableCollection<Product>();

    public Flashlist(List<Product> itemList) {
        if (itemList == null) return;
        foreach (var itm in itemList) Items.Add(itm);
    }

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

3. 重写InitAsync方法,正确更新集合并绑定过滤视图

先在页面构造函数中初始化持久的Flashlist实例,用ICollectionView处理过滤逻辑,确保UI能自动感知集合变化:

private Flashlist _items;

public YourPage() {
    InitializeComponent();
    // 初始化空集合,保持引用不变
    _items = new Flashlist(null);
    // 用ICollectionView实现过滤,替代ToList()生成的静态List
    var filteredView = CollectionViewSource.GetDefaultView(_items.Items);
    filteredView.Filter = item => ((Product)item).status == "publish";
    // 绑定到过滤后的视图
    productsListView.FlowItemsSource = filteredView;
}

private async Task InitAsync() {
    try {
        var rest = new RestAPI("http://Site/wp-json/wc/v3/", "xxxxxxxxx", "xxxxxxx");
        var wc = new WCObject(rest);
        // 网络请求放在后台线程不影响UI
        var product = await wc.Product.GetAll(new Dictionary<string, string> {
            {"tag", "1486"}, {"per_page", "80"}
        });

        // 确保集合更新操作在UI线程执行
        Device.BeginInvokeOnMainThread(() => {
            if (product != null) {
                // 清空原有数据,添加新数据——保持集合引用不变
                _items.Items.Clear();
                foreach (var prod in product) {
                    _items.Items.Add(prod);
                }
            } else {
                _items.Items.Clear();
            }
            // 手动刷新过滤视图(如果自动刷新不生效的话)
            // CollectionViewSource.GetDefaultView(_items.Items).Refresh();
        });
    } catch (Exception ex) {
        Crashes.TrackError(ex);
        Analytics.TrackEvent(ex.ToString());
    }
}

为什么这样修改能解决问题

  • 去掉Task.Run后,集合更新操作回到UI线程,符合Xamarin.Forms的UI更新规则;
  • 保持ObservableCollection的引用不变,通过Clear+Add更新内容,能正常触发CollectionChanged事件通知UI;
  • 用ICollectionView处理过滤,替代静态List,过滤后的视图会自动跟随原集合的变化同步更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 19:48:12