Xamarin.Forms MVVM开发中ObservableCollection找不到AddRange方法问题求助
问题根因
原生.NET 类库中的 System.Collections.ObjectModel.ObservableCollection<T> 本身没有内置AddRange方法,你虽然已经引用了Xamarin.CommunityToolkit.ObjectModel命名空间,但当前声明的ProductsList用的是原生ObservableCollection类型,并非社区工具包封装的支持批量操作的集合类型。
此外你当前的MyDisplayList方法存在异步调用未加await的问题,就算AddRange可用,直接传入Task类型的返回值也会触发参数类型不匹配报错。
解决方案
方案1:使用Xamarin Community Toolkit提供的ObservableRangeCollection<T>(最适配你的现有依赖)
你已经引用了Xamarin社区工具包的命名空间,直接把集合类型替换为ObservableRangeCollection<T>即可,该类型原生支持AddRange、RemoveRange等批量操作方法,修改代码如下:
// 替换集合声明的类型 public ObservableRangeCollection<ProductModel> ProductsList { get; set; } public ProductViewModel() { ProductsList = new ObservableRangeCollection<ProductModel>(); } public async Task MyDisplayList() { // 补上await获取实际的集合返回值 var getData = await ProductService.DisplayProduct(); ProductsList.AddRange(getData); }
方案2:自定义AddRange扩展方法
如果你不想更换集合类型,可以自己实现扩展方法适配原生ObservableCollection:
public static class ObservableCollectionExtensions { public static void AddRange<T>(this ObservableCollection<T> collection, IEnumerable<T> items) { if (collection == null) throw new ArgumentNullException(nameof(collection)); if (items == null) throw new ArgumentNullException(nameof(items)); foreach (var item in items) { collection.Add(item); } } }
如果需要优化大量数据批量添加的性能,可以禁用单次添加的事件通知,批量添加完成后一次性触发更新:
public static class ObservableCollectionExtensions { public static void AddRange<T>(this ObservableCollection<T> collection, IEnumerable<T> items, bool suppressSingleNotification = true) { if (collection == null) throw new ArgumentNullException(nameof(collection)); if (items == null) throw new ArgumentNullException(nameof(items)); if (!suppressSingleNotification) { foreach (var item in items) collection.Add(item); return; } // 反射调用重入锁定方法,避免多次触发事件 var blockMethod = typeof(ObservableCollection<T>).GetMethod("BlockReentrancy", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); using ((IDisposable)blockMethod.Invoke(collection, null)) { foreach (var item in items) { collection.Items.Add(item); } // 手动触发集合重置通知 collection.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } } }
方案3:直接替换集合实例
如果是首次加载列表无历史缓存数据,可以直接给集合赋值新实例,同时触发属性变更通知即可:
public async Task MyDisplayList() { var getData = await ProductService.DisplayProduct(); ProductsList = new ObservableCollection<ProductModel>(getData); // 调用你ViewModel中实现的INotifyPropertyChanged通知方法 OnPropertyChanged(nameof(ProductsList)); }
内容的提问来源于stack exchange,提问作者user9207271
相关产品推荐
相关产品推荐

