Xamarin.Forms列表分页加载问题:初始12条,滚动加载更多
Xamarin.Forms 实现列表分页加载(初始12条,滚动加载更多)
Xamarin.Forms.Extended.InfiniteScrolling确实已废弃,无需额外NuGet包,Xamarin.Forms自带的CollectionView和ListView都原生支持无限滚动功能,以下是完整实现方案:
核心思路
- 先一次性加载全部CSV数据(若数据量极大,建议改为从数据源分批拉取)
- 用
ObservableCollection绑定列表,确保新增数据时UI自动更新 - 分页逻辑:每页加载12条,滚动到底部时加载下一页
修改后的完整代码
XAML代码
<!-- 优先使用的CollectionView --> <CollectionView SelectionMode="Single" x:Name="listview" SelectionChanged="listview_SelectionChanged" IsVisible="true" RemainingItemsThreshold="4" RemainingItemsThresholdReached="OnRemainingItemsThresholdReached" ItemsLayout="VerticalGrid, 2"> <CollectionView.ItemTemplate> <DataTemplate> <Grid Padding="18"> <Grid.RowDefinitions> <RowDefinition Height="auto" /> <RowDefinition Height="auto" /> <RowDefinition Height="auto" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Label Text="{Binding prod_img}" TextColor="#289" Grid.RowSpan="3" Grid.Column="0" HeightRequest="80" WidthRequest="80" /> <Label Text="{Binding prod_name}" TextColor="Black" FontSize="Medium" FontAttributes="Bold" Grid.Column="1" Grid.Row="0"/> <StackLayout Grid.Row="1" Grid.Column="1" Orientation="Horizontal"> <Label Text="Rs." TextColor="Black"/> <Label Text="{Binding prod_price}" TextColor="Black" LineBreakMode="TailTruncation"/> </StackLayout> </Grid> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> <!-- 保留的ListView(如需使用) --> <ListView x:Name="listview2" HasUnevenRows="True" IsVisible="false" ItemSelected="listview2_ItemSelected" ItemAppearing="ListView2_ItemAppearing"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <Grid Padding="18"> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition Height="auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Label Text="{Binding prod_img}" TextColor="#289" Grid.RowSpan="2" Grid.Column="0" HeightRequest="80" WidthRequest="80" /> <Label Text="{Binding prod_name}" TextColor="Black" FontSize="Medium" FontAttributes="Bold" Grid.Column="1"/> <Label Text="{Binding prod_price}" TextColor="Black" Grid.Row="1" Grid.Column="1" LineBreakMode="TailTruncation"/> </Grid> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView>
Xaml.cs代码
public partial class import : ContentPage { private List<csv> _allItems; private ObservableCollection<csv> _displayedItems; private int _currentPage = 1; private const int PageSize = 12; public import() { InitializeComponent(); _displayedItems = new ObservableCollection<csv>(); listview.ItemsSource = _displayedItems; listview2.ItemsSource = _displayedItems; } protected async override void OnAppearing() { base.OnAppearing(); // 首次加载全部数据,再分页展示 _allItems = await filelist(); LoadNextPage(); } // CollectionView滚动到底部触发加载 private void OnRemainingItemsThresholdReached(object sender, EventArgs e) { LoadNextPage(); } // ListView滚动到底部触发加载 private void ListView2_ItemAppearing(object sender, ItemVisibilityEventArgs e) { if (_displayedItems == null || _displayedItems.Count == 0) return; if (e.Item != _displayedItems[_displayedItems.Count - 1]) return; LoadNextPage(); } // 加载下一页数据 private void LoadNextPage() { var skip = (_currentPage - 1) * PageSize; var nextItems = _allItems.Skip(skip).Take(PageSize).ToList(); if (nextItems.Count == 0) return; foreach (var item in nextItems) { _displayedItems.Add(item); } _currentPage++; } private Task<List<csv>> filelist() { var assembly = IntrospectionExtensions.GetTypeInfo(typeof(MainPage)).Assembly; Stream stream = assembly.GetManifestResourceStream("Todolist.WP.csv"); List<csv> lstSample = new List<csv>(); using (var reader = new System.IO.StreamReader(stream)) { if (reader != null) { using (var csvReader = new CsvReader(reader, CultureInfo.CurrentCulture)) { while (csvReader.Read()) { lstSample.Add(new csv { prod_name = csvReader.GetField<string>(2), prod_img = csvReader.GetField<string>(18), prod_price = csvReader.GetField<int>(13), prod_desc = csvReader.GetField<string>(3), prod_m_w = csvReader.GetField<string>(6), Prod_cate = csvReader.GetField<string>(5) }); } } } } return Task.FromResult(lstSample); } } // 补充csv实体类(若未定义) public class csv { public string prod_name { get; set; } public string prod_img { get; set; } public int prod_price { get; set; } public string prod_desc { get; set; } public string prod_m_w { get; set; } public string Prod_cate { get; set; } }
关键说明
ObservableCollection负责绑定列表,新增数据时自动刷新UIPageSize固定为12,匹配需求的每页加载条数CollectionView通过RemainingItemsThreshold设置提前触发加载的阈值,RemainingItemsThresholdReached事件处理加载逻辑ListView通过ItemAppearing事件检测滚动到最后一项,触发加载下一页- 首次进入页面加载第一页,之后每次滚动到底部自动加载下一页,直到无更多数据
内容的提问来源于stack exchange,提问作者Vired
相关产品推荐
相关产品推荐

