当列表视图滚动到达最后一项/无限滚动列表视图时,UWP列表视图会加载更多数据

时间:2018-08-08 06:41:26

标签: c# listview uwp windows-10-universal uwp-xaml

我的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;
        } 
    }

应用开始限制为100,列表到达末尾时,必须将限制设置为200或接下来的100个项目,然后再次进行API调用。

我试图通过pointerEntered事件来实现。但是,无法实现上述功能,因为它仅将分配给listview的高度与指针高度匹配,因此将不会工作,因为scrollviewer的高度可以变化。我什至试图访问scrollviewer,但是不能!

我还引用了以下URL:How do I allow a UWP ListView to scroll past the last item? && Detect when WPF listview scrollbar is at the bottom? && 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应用程序上工作且未获胜8

1 个答案:

答案 0 :(得分:1)

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

这意味着您将无法像问题中那样假设地控制数据的加载,但我仍然认为它可以满足您的需求:

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

首先介绍一些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将绑定到item集合,该集合用于item模板
  2. DataFetchSize,到结束时要提取的数量:以PAGES为单位。 (让我困惑了片刻)
  3. IncrementalLoadingTrigger,请参见msdn
  4. IncrementalLoadingThreshold,请参见msdn

然后...,代码:

首先是一个可观察的自定义集合:这也是您的加载例程:

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           
    }
}

可以找到更多信息here