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

Xamarin.Forms列表分页加载问题:初始12条,滚动加载更多

Xamarin.Forms 实现列表分页加载(初始12条,滚动加载更多)

Xamarin.Forms.Extended.InfiniteScrolling确实已废弃,无需额外NuGet包,Xamarin.Forms自带的CollectionView和ListView都原生支持无限滚动功能,以下是完整实现方案:

核心思路

  1. 先一次性加载全部CSV数据(若数据量极大,建议改为从数据源分批拉取)
  2. 用ObservableCollection绑定列表,确保新增数据时UI自动更新
  3. 分页逻辑:每页加载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负责绑定列表,新增数据时自动刷新UI
  • PageSize固定为12,匹配需求的每页加载条数
  • CollectionView通过RemainingItemsThreshold设置提前触发加载的阈值,RemainingItemsThresholdReached事件处理加载逻辑
  • ListView通过ItemAppearing事件检测滚动到最后一项,触发加载下一页
  • 首次进入页面加载第一页,之后每次滚动到底部自动加载下一页,直到无更多数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 12:40:25