UWP列表视图:当滚动到最后一个项目时加载更多数据/无限滚动列表视图。

5

我在我的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:如何允许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

但是,它们都没有在我的情况下实际起作用。

我尝试查找一个事件来实现此功能,但没有找到任何内容。

有人可以提供关于如何检测listview滚动是否到达末尾(列表中的最后一个项目)的想法吗?

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


@Stefan lstSuggestions_PointerEntered 函数在指针移动到 listview 区域/部分时被调用。它只是捕获指针是否在 listview UI 区域内。 - ace
我似乎看不出你的实际问题在哪里。这些项目是否已添加到列表视图中?如果是,您能否将它们滚动到视图中? - Stefan
@Stefan 首先将前100个项目添加到列表视图中,并且可以滚动。现在假设用户滚动到最后一个项目,我想要加载下一个100个项目到列表视图中。我在问题中也提到了同样的事情。 - ace
我的代码将在 ListView 中加载前 100 个项目,一旦滚动到最后一个项/底部,它应该会加载另外 100 个项目。在这种情况下,是否包括 lstSuggestions_PointerEntered 并不重要。您可以参考此答案:检测 WPF ListView 滚动条是否到达底部?,然而它在我的情况下没有起到帮助作用。 - ace
好的,我有一段时间没有做这个了,但通常我会使用更多的MVVM方法,为列表视图使用ItemSource并在最后一个项目可见时触发加载。我以前在Xamarin和WP8上做过这个,所以我认为对于UWP来说应该是类似的。...我会尝试把它包装起来。 - Stefan
显示剩余3条评论
1个回答

7

这有点不同,它使用ListView增量加载功能来创建无限滚动列表。

这意味着您对数据的加载没有像您在问题中所假设的那样多的控制权,但我仍然认为它可以满足您的需求:

它使用MVVM绑定,因此没有使用典型的UI事件。如果您不了解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. ItemsSource 绑定到项集合,它在项模板中使用。
  2. DataFetchSize 是达到末尾时获取的数量(以页为单位)。 (曾经让我有些困惑)
  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 };
        });
    }
}

我们正在使用一个新的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           
    }
}

更多信息可以在此处找到。


嘿,感谢您宝贵的意见,我会仔细查看您建议的更改,并在一段时间后告诉您。 - ace
我能否简单地执行lstSuggestions.add(new Item(name, id)),因为lstSuggestions依赖于其他功能。我正在使用lstSuggestions来实现其他功能。如果我按照您的建议进行更改,那么在这种情况下,我将无法使用lstSuggestions - ace
1
嗨,最好提出一个新问题,可能参考这个问题,这样你就能得到充分的关注和最好的机会得到你的问题的答案;-) - Stefan
希望您能为这个问题提供有价值的建议:在懒加载的ListView中实现SearchBox功能 - ace
抱歉,我对这些控件不熟悉。也许你可以在 Stack Overflow 上提出问题。 - Stefan
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接