WP8.1 Universal:从ISupportIncrementalLoading中正确取消并重启LoadMoreItemsAsync

WP8.1 Universal: Properly cancel and restart LoadMoreItemsAsync from ISupportIncrementalLoading

为了在我的 WP8.1 通用应用程序中实现无限滚动,我实现了 ISupportIncrementalLoading 并使用结果绑定到我的 ListView。使用此代码可以正常工作:

public sealed class IncrementalLoadingCollection<T, I> : ObservableCollection<I>, ISupportIncrementalLoading
    where T : IIncrementalSource<I>, new()
{
    private int currentPage;
    private bool hasMoreItems;
    private int itemsPerPage;
    private T source;

    public IncrementalLoadingCollection(int itemsPerPage = 10)
    {
        this.source = new T();
        this.itemsPerPage = itemsPerPage;
        this.hasMoreItems = true;
    }

    public bool HasMoreItems
    {
        get { return this.hasMoreItems; }
    }

    public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
    {
        return AsyncInfo.Run(c => LoadMoreItemsAsync(c, count));
    }

    private async Task<LoadMoreItemsResult> LoadMoreItemsAsync(CancellationToken cancellationToken, uint count)
    {
        var dispatcher = Window.Current.Dispatcher;

        var task = await Task.Run<LoadMoreItemsResult>(
            async () =>
            {
                if (Count == 0 && this.currentPage > 0)
                {
                    this.currentPage = 0; // this was cleared
                }
                uint resultCount = 0;

                var result = await this.source.GetPagedItems(cancellationToken, this.currentPage, this.itemsPerPage);

                this.currentPage++;

                if (result == null || !result.Any())
                {
                    this.hasMoreItems = false;
                }
                else
                {
                    resultCount = (uint)result.Count();

                    await dispatcher.RunAsync(
                        CoreDispatcherPriority.Normal,
                        () =>
                        {
                            foreach (I item in result)
                            {
                                Add(item);
                            }
                        });
                }

                return new LoadMoreItemsResult { Count = resultCount };
            }, cancellationToken);
        return task;
    }
}

现在我正在尝试清除所有已加载的项目并使用此代码从不同的 url(用户应该能够切换 "category")加载新数据:

public void ClearAndSetNewUrl(string newUrl)
    {
        if (this.LoadMoreItemsAsync((uint) this.itemsPerPage).Status == AsyncStatus.Started)
        {
            this.LoadMoreItemsAsync((uint) this.itemsPerPage).Cancel();
        }
        this.source.SetUrl(newUrl);
        this.hasMoreItems = true;
        base.ClearItems();
    }

但是结果中经常填充旧 url 的结果(可能是因为异步查询)或者 hasMoreItems 设置为 false and/or 增量加载停止工作。

删除所有以前的项目、停止从旧 url 加载的所有任务并仅从新 url 开始加载的正确方法是什么?

使用其他参数(新 uri、类别等)创建您的 IncrementalLoadingCollection 的新实例,并为 ListView 的 ItemsSource 重置它。所以它应该有所帮助。

更新

public class MyViewModel : PropertyChangeBase
{
      public ThemeEventsDataSource ItemsSource
        {
            get { return _itemsSource; }
            set
            {
                if (Equals(value, _itemsSource)) return;
                _itemsSource = value;
                NotifyOfPropertyChange();
            }
        }
}

public class ThemeEventsDataSource : ObservableCollection<ThemeEventViewModel>, ISupportIncrementalLoading
    {
        public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
        {
            return AsyncInfo.Run(c => LoadMoreThemeEventsAsync(count));
        }

         private async Task<LoadMoreItemsResult> LoadMoreThemeEventsAsync(uint count)
{
//TODO: your code for Getting data
this.Add(...);
return new LoadMoreItemsResult { Count = (uint)items.Length };
}
    }

因此,当您需要更改上下文(更改 uri、更改过滤器等)时,您应该使用指定的参数创建新的 ThemeEventsDataSource 并将此通知 UI。