1

In order to have endless scrolling in my WP8.1 universal app I've implemented ISupportIncrementalLoading and I'm using the result to bind to my ListView. Works fine with this code:

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

Now I'm trying to clear all loaded items and load the new data from a different url (user should be able switch the "category") with this code:

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();
    }

But the results are often populated with results from the old url (probably because of async query) or hasMoreItems is set to false and/or incremental loading stops to work.

What's a proper way to get rid of all previous items, stop all tasks that are loading from the old url and start loading only from new url?

Mr.T
  • 15
  • 4

1 Answers1

0

Create new instance of your IncrementalLoadingCollection with another arguments (new uri, category, etc.) and reset it for ItemsSource of ListView. So it should help.

UPDATE

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

So when, you need change context (changed uri, changed filters, etc.) you should create new ThemeEventsDataSource with specified parametres and notify UI about this.

Roman Golenok
  • 1,327
  • 8
  • 24