导航离开后,ISupportIncrementalLoading不会停止

时间:2021-07-21 21:13:41

I suddenly found a strange behavior of collection implementing ISupportIncrementalLoading. Let's say we have a main page with ISupportIncrementalLoading collection bound to ListView. And we have another page where we can navigate to. When navigating to main page, the ISupportIncrementalLoading starts loading items until ListView thinks it's enough. I navigate to new page BEFORE ListView loaded all items it needs. My expected behavior: ListView stops loading new items as the page isn't visible now. Real behavior: ListView continues to load items endlessly, even after going away from the page. And it won't stop until gets HasMore == false. Can anyone help with this? This is absolutely wrong behavior.

我突然发现了一个实现ISupportIncrementalLoading的集合的奇怪行为。假设我们有一个主页面,其中ISupportIncrementalLoading集合绑定到ListView。我们还有另一个页面可以导航到。导航到主页面时,ISupportIncrementalLoading开始加载项目,直到ListView认为它已足够。我导航到新页面之前,ListView加载了所需的所有项目。我的预期行为:ListView停止加载新项目,因为页面现在不可见。真实行为:ListView继续无休止地加载项目,即使离开页面也是如此。并且在获取HasMore == false之前不会停止。有人能帮忙吗?这绝对是错误的行为。

PS

If I while navigation, set in ViewModel the collection to null and then restore it when coming back -- it seams to help, but that is too much to do, I think.

如果我在导航时,在ViewModel中将集合设置为null,然后在返回时恢复它 - 它接缝有帮助,但我认为这太多了。

Here's the code of my basic ISupportIncrementalLoading collection:

这是我的基本ISupportIncrementalLoading集合的代码:

public abstract class BaseIncrementalSupportCollection<T> :IList<T>,IList,INotifyCollectionChanged, ISupportIncrementalLoading, INotifyPropertyChanged
{
    protected readonly List<T> storage;

    private bool isLoading;
    public bool IsLoading
    {
        get
        {
            return isLoading;
        }
        set
        {
            if (isLoading != value)
            {
                isLoading = value;
                RaisePropertyChanged();
            }
        }
    }

    public bool failed;

    public bool IsFailed
    {
        get { return failed; }
        set
        {
            if (failed != value)
            {
                failed = value;
                RaisePropertyChanged();
            }
        }
    }

    public bool IsEmpty
    {
        get { return !HasMoreItems && Count == 0; }
    }

    protected BaseIncrementalSupportCollection()
    {
        storage = new List<T>();
    }

    public virtual IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
    {
        return Task.Run(()=>LoadMoreItems(count)).AsAsyncOperation();
    }

    public abstract bool HasMoreItems { get; }


    private async Task<LoadMoreItemsResult> LoadMoreItems(uint count)
    {
        IsLoading = true;
        IsFailed = false;
        try
        {
            var items = await LoadMoreItemsOverride(count);
            if (items == null)
                return new LoadMoreItemsResult() {Count = 0};
            if (items.Count > 0)
            {
                var prevEmptyState = IsEmpty;
                foreach (var item in items)
                {
                    var currItem = item;
                    await DispatchHelper.RunOnUiIfNecessary(async () =>
                    {
                        storage.Add(currItem);
                        RaiseCollectionChanged(
                            new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, currItem,
                                storage.Count - 1));
                    });
                }
                if(prevEmptyState!=IsEmpty)
                    RaisePropertyChanged("IsEmpty");

            }
            return new LoadMoreItemsResult() {Count = (uint) items.Count};
        }
        catch (Exception e)
        {
            var aggregate = e as AggregateException;
            if (aggregate != null)
                e = aggregate.Flatten().InnerException;
            IsFailed = true;
            var handler = OnError;
            if (handler != null)
                DispatchHelper.RunOnUiIfNecessary(
                    () => handler(this, new IncrementallCollectionLoadErrorEventArgs(e)));
            return new LoadMoreItemsResult() {Count = 0};
        }
        finally
        {
            IsLoading = false;
        }

    }

    protected virtual void RaiseCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        if (CollectionChanged != null)
            CollectionChanged(this, e);
    }

    protected abstract Task<IList<T>> LoadMoreItemsOverride(uint count);

    [NotifyPropertyChangedInvocator]
    protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null)
            DispatchHelper.RunOnUiIfNecessary(()=>handler(this, new PropertyChangedEventArgs(propertyName)));
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public event EventHandler<IncrementallCollectionLoadErrorEventArgs> OnError;
    public event NotifyCollectionChangedEventHandler CollectionChanged;
}

1 个解决方案

#1


I've just found another way, adding additional bool field isStopped with methods Start, ForceStop setting it to false/true. This value is used when getting HasMoreItems like

我刚刚找到另一种方法,添加额外的bool字段isStopped方法Start,ForceStop将其设置为false / true。获取HasMoreItems时使用此值

bool HasMoreItems{get{return !isStopped && DetermineIfHasMore()};}

bool HasMoreItems {get {return!isStopped && DetermineIfHasMore()};}

And simply by calling those to methods I can stop or continue loading the same collection generator.

简单地通过调用那些方法我可以停止或继续加载相同的集合生成器。

Another way is provided here https://social.msdn.microsoft.com/Forums/ru-RU/be17357d-faac-4f49-acf4-e916fcdace9d/w81isupportincrementalloading-doesnt-stop-after-navigating-away?forum=winappswithcsharp

另一种方法是在这里提供https://social.msdn.microsoft.com/Forums/ru-RU/be17357d-faac-4f49-acf4-e916fcdace9d/w81isupportincrementalloading-doesnt-stop-after-navigating-away?forum=winappswithcsharp

#1


I've just found another way, adding additional bool field isStopped with methods Start, ForceStop setting it to false/true. This value is used when getting HasMoreItems like

我刚刚找到另一种方法,添加额外的bool字段isStopped方法Start,ForceStop将其设置为false / true。获取HasMoreItems时使用此值

bool HasMoreItems{get{return !isStopped && DetermineIfHasMore()};}

bool HasMoreItems {get {return!isStopped && DetermineIfHasMore()};}

And simply by calling those to methods I can stop or continue loading the same collection generator.

简单地通过调用那些方法我可以停止或继续加载相同的集合生成器。

Another way is provided here https://social.msdn.microsoft.com/Forums/ru-RU/be17357d-faac-4f49-acf4-e916fcdace9d/w81isupportincrementalloading-doesnt-stop-after-navigating-away?forum=winappswithcsharp

另一种方法是在这里提供https://social.msdn.microsoft.com/Forums/ru-RU/be17357d-faac-4f49-acf4-e916fcdace9d/w81isupportincrementalloading-doesnt-stop-after-navigating-away?forum=winappswithcsharp