AdvancedCollectionView实现ISupportIncrementalLoading后,ListView仍全量加载问题排查
你遇到的问题主要有两个核心原因,咱们一步步拆解:
1. AdvancedCollectionView 默认不支持增量加载
Windows Community Toolkit 中的 AdvancedCollectionView 本身没有实现 ISupportIncrementalLoading 接口——ListView 识别增量加载的前提是绑定的集合必须实现这个接口,否则哪怕你设置了 IncrementalLoadingTrigger、DataFetchSize 这些属性,ListView 也只会一次性加载所有数据。
另外,你的源集合 DocCollection 是 ObservableCollection<Document>,它同样不支持增量加载,所以 AdvancedCollectionView 也没法从它那里获得分批加载的能力。
2. XAML 中的属性拼写错误
你写的 ItemSource 是拼写错误,正确的属性名是 ItemsSource(多一个s)。虽然你说 ListView 加载了所有项,可能是实际代码里没写错,但这个细节很容易踩坑,必须注意!
解决方案:实现支持增量加载的集合
咱们有两种可行的方案,你可以根据自己的场景选择:
方案一:让源集合实现 ISupportIncrementalLoading
创建一个继承自 ObservableCollection<Document> 并实现 ISupportIncrementalLoading 的集合类,把分批加载的逻辑写在这里:
public class IncrementalDocumentCollection : ObservableCollection<Document>, ISupportIncrementalLoading { private int _currentPage = 0; private const int PageSize = 10; // 和 ListView 的 DataFetchSize 保持一致 // 判断是否还有更多数据可以加载 public bool HasMoreItems => _currentPage * PageSize < 1000; // 你的总数据量是1000 // 核心的加载方法 public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count) { return AsyncInfo.Run(async (cancellationToken) => { // 计算本次要加载的数量,避免超过总数据量 var itemsToLoad = (int)Math.Min(count, 1000 - _currentPage * PageSize); // 模拟异步加载(实际场景替换成从API/数据库获取数据的逻辑) await Task.Delay(500); // 模拟网络延迟 // 添加加载到的项到集合中 for (int i = 0; i < itemsToLoad; i++) { Add(new Document { // 这里初始化你的 Document 对象,比如 ID = _currentPage * PageSize + i + 1 }); } _currentPage++; return new LoadMoreItemsResult { Count = (uint)itemsToLoad }; }); } }
然后在后台代码中替换掉原来的 ObservableCollection:
public class MainPage { public AdvancedCollectionView ACV { get; set; } public IncrementalDocumentCollection DocCollection; public MainPage() { InitializeComponent(); // 别忘了这句,初始化页面元素 DocCollection = new IncrementalDocumentCollection(); ACV = new AdvancedCollectionView(DocCollection, true); } }
方案二:封装 AdvancedCollectionView 使其支持增量加载
如果不想修改源集合,可以创建一个继承自 AdvancedCollectionView 并实现 ISupportIncrementalLoading 的类,把增量加载逻辑委托给源集合:
public class IncrementalAdvancedCollectionView : AdvancedCollectionView, ISupportIncrementalLoading { private readonly ISupportIncrementalLoading _sourceIncremental; public IncrementalAdvancedCollectionView(ISupportIncrementalLoading source, bool isLiveShapingEnabled) : base((IEnumerable)source, isLiveShapingEnabled) { _sourceIncremental = source; } public bool HasMoreItems => _sourceIncremental.HasMoreItems; public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count) { return AsyncInfo.Run(async (token) => { // 直接调用源集合的加载方法,ACV会自动同步更新 var result = await _sourceIncremental.LoadMoreItemsAsync(count); return result; }); } }
使用时只需要把原来的 AdvancedCollectionView 替换成这个封装类:
public MainPage() { InitializeComponent(); DocCollection = new IncrementalDocumentCollection(); ACV = new IncrementalAdvancedCollectionView(DocCollection, true); }
额外注意事项
- 把 XAML 中的
ItemSource改成ItemsSource,并且Mode=TwoWay是不必要的(ListView 不会修改集合本身),可以改成Mode=OneWay:<ListView x:Name="MyListView" DataFetchSize="10" IncrementalLoadingTrigger="Edge" IncrementalLoadingThreshold="10" ItemsSource="{x:Bind ACV, Mode=OneWay}"> </ListView> - 如果你的数据加载逻辑涉及复杂操作(比如网络请求),记得处理取消令牌(
cancellationToken),避免内存泄漏。
内容的提问来源于stack exchange,提问作者LeBrown Jones

