首页 > 解决方案 > 当列表视图滚动到最后一项/无限滚动列表视图时,UWP 列表视图加载更多数据

问题描述

我的 UWP (Windows 10) 应用程序中有一个列表视图。理想情况下,它会在应用程序启动时加载 100 个项目。

当列表滚动到底部,即列表视图中的最后一项时,API 调用将继续并加载另外 100 个项目等等。

这是我的代码:

<ListView x:Name="lstSuggestions" Height="200" Width="250" Foreground="#333eb4" HorizontalAlignment="Left" Margin="60,10" SelectionChanged="lstSuggestions_SelectionChanged"></ListView>

以下调用绑定列表视图(应用程序启动时的前 100 个项目):

public async void GetData(string Id, string limit)
    { 
        string mainUrlForSuggestions = ApiUrl +  "&id=" + d;
        string finalSelCharas = "";

        using (var httpClient = new HttpClient())
        {
            var dataUri = await httpClient.GetStringAsync(mainUrlForSuggestions);
            JsonObject jsonObject = JsonObject.Parse(dataUri.ToString());
            JsonArray jsonArray = jsonObject["payload"].GetArray();
            foreach (JsonValue groupValue in jsonArray)
            {
                JsonObject groupObject = groupValue.GetObject();
                lstSuggestionsAdd.Add(new SuggestedWords { Name = groupObject.GetNamedString("sug_name"), ID = groupObject.GetNamedString("id") });
            }
            lstSuggestions.ItemsSource = lstSuggestionsAdd;
        } 
    }

on app start limit 是 100,一旦列表结束,它必须将限制设置为 200 或下 100 个项目并再次进行 API 调用。

我试图通过 pointerEntered 事件来实现这一点。但是,无法实现上述功能,因为它仅将分配给列表视图的高度与指针高度相匹配,因此当滚动查看器高度可能变化时,它不会起作用。我什至试图访问scrollviewer,但不能!

我还提到了以下 URL:如何允许 UWP ListView 滚动过去最后一项? && 检测 WPF listview 滚动条何时位于底部? && https://social.msdn.microsoft.com/Forums/windows/en-US/63b4b530-61d8-477f-af96-87e33260c919/uwa-how-to-detect-the-end-and-the-start-of -listview-and-load-more-data-items?forum=wpdevelop

但在我的情况下,它们都没有真正起作用。

我试图找到一个事件来实现这个功能,但没有找到。

谁能给出一个关于如何检测列表视图滚动是否结束(列表视图中的最后一项)的想法???

请注意,我正在使用 Windows 10 UWP 应用程序而不是 win 8

标签: c#listviewuwpwindows-10-universaluwp-xaml

解决方案


好的,有点不同,它使用 ListView 的incremental loading功能来创建无限滚动列表。

这意味着您不会像您在问题中假设的那样控制加载数据,但我仍然认为它会满足您的需求:

它使用一些 MVVM 绑定,因此实际上没有使用任何事件。如果您对MVVM不了解,请尝试了解一下。

首先是一些 XAML,默认主页:

<Page
    x:Class="App6.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App6"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DataContext="{d:DesignInstance local:ViewModel, IsDesignTimeCreatable=True}">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <ListView ItemsSource="{Binding Items}" 
                  DataFetchSize="1" 
                  IncrementalLoadingTrigger="Edge" 
                  IncrementalLoadingThreshold="5">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <TextBlock Text="{Binding Text}"></TextBlock>
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Page>

注意 ItemsSource="{Binding Items}" DataFetchSize="1" IncrementalLoadingTrigger="Edge" IncrementalLoadingThreshold="5"

  1. ItemSource 将绑定到项目集合,它在项目模板中使用
  2. DataFetchSize,到达末尾时要获取的数量:以 PAGES 为单位。(让我困惑了一会儿)
  3. IncrementalLoadingTrigger,见msdn
  4. IncrementalLoadingThreshold,见msdn

然后...,代码:

首先是一个自定义的 observable 集合:这也是你的加载例程:

public class IncrementalLoadingCollection : ObservableCollection<Item>, ISupportIncrementalLoading
{
    uint x = 0; //just for the example
    public bool HasMoreItems { get { return x < 10000; } } //maximum

    //the count is the number requested
    public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
    {
        return AsyncInfo.Run(async cancelToken =>
        {
            //here you need to do your loading
            for (var c = x; c < x + count; c++)
            {
                //add your newly loaded item to the collection
                Add(new Item()
                {
                    Text = c.ToString()
                });
            }

            x += count;
            //return the actual number of items loaded (here it's just maxed)
            return new LoadMoreItemsResult { Count = count };
        });
    }
}

我们正在使用一个new Item类,所以让我们定义它:

//the type which is being used to display the data
//you could extend it to use images and stuff
public class Item
{
    public string Text { get; set; }
}

让我们创建一个视图模型:

public class ViewModel
{
    public ViewModel()
    {
        Items = new IncrementalLoadingCollection();
    }
    //using the custom collection: these are your loaded items
    public IncrementalLoadingCollection Items { get; set; }
}

将其包装在后面的代码中:我们使用数据上下文:

/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        DataContext= new ViewModel(); //using a viewmodel as data context           
    }
}

更多信息可以在这里找到


推荐阅读