ISupportIncrementalLoading Collection - notify UI when LoadingMoreItems is in progress

耗尽温柔 提交于 2020-01-01 19:54:06

问题


I've have created a IncrementalLoadingCollection class in my app which implements ISupportIncrementalLoading and inherits from ObservableCollection< T >.

It works fine and the items are loaded but I would like to show a message on the app's Status Bar that there is some work in progress.

What's a good way of achieving this?

Since LoadMoreItemsAsync is called internally when the list is scrolled, I cannot access that part to come up with the code which updates the Status Bar. Right now, I am doing this in LoadMoreItemsAsync which I find it a terrible approach, but I couldn't find a better one so far...

Any suggestions are highly appreciated.


回答1:


Well you can for example: inherit from ObservableCollection and implement ISupportIncrementalLoading like this:

class IncrementalLoadingObservableCollection<T> : ObservableCollection<T>, ISupportIncrementalLoading
{
    private readonly Func<CancellationToken, Task<IEnumerable<T>>> _provideMoreItems;

    public IncrementalLoadingObservableCollection(Func<CancellationToken, Task<IEnumerable<T>> provideMoreItems)
    {
        _provideMoreItems = provideMoreItems;
    }

    public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
    {
        return AsyncInfo.Run(async cancelToken =>
        {
            await Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                OnLoadMoreItemsStarted();
            });

            var providedItems = await _provideMoreItems(cancelToken);

            await Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                foreach(var item in providedItems)
                    Add(item);

                OnLoadMoreItemsCompleted();
            });

            return new LoadMoreItemsResult {Count = (uint) providedItems.Count()};;
        });
    }

    public bool HasMoreItems
    {
        get { return true; }
    }

    public event Action LoadMoreItemsStarted;
    public event Action LoadMoreItemsCompleted;

    protected virtual void OnLoadMoreItemsStarted()
    {
        var handler = LoadMoreItemsStarted;
        if (handler != null) handler();
    }

    protected virtual void OnLoadMoreItemsCompleted()
    {
        var handler = LoadMoreItemsCompleted;
        if (handler != null) handler();
    }
}

How to use it? In your ViewModel:

class MyFancyItemsViewModel
{
     public MyFancyItemsViewModel()
     {  
         var incrementalObservablCollcetion = new IncrementalLoading...(GetItemsFromInternetOrSmth);
         incrementalObservablCollcetion.LoadMoreItemsStarted += OnItemsLoadingStarted;
         incrementalObservablCollcetion.LoadMoreItemsCompleted += OnItemsLoadingCompleted;

          ItemsBindedInXaml = incrementalObservablCollcetion;
     }

     private Task<IEnumerable<Items>> GetItemsFromInternetOrSmth(CancellationToken cancelToken)
     {
      ... do some work returns enumerable of Items
     }

     private void OnItemsLoadingStarted()
     { .. do smth .. }

     private void OnItemsLoadingCompleted()
     { ... do smth .. } 

     public ObservableCollection<Items> ItemsBindedInXaml { get; private set; }
}

You might ask why I have used Dispatcher.RunAsync in IncrementalLoadingObservableCollection - the reason is that LoadMoreItemsAsync might run on another thread (don't know that) so you have to dispatch all the work to the UI Thread (it's not possible to call UI-related methods from thread other than UI thread without use of Dispatcher).

If you feel that ViewModel is not appropiate place for UI-related operations take a look at some messaging mechanisms (like MVVM Light Messenger, register message in code-behind and send this message in LoadMoreItemsStarted handler)



来源:https://stackoverflow.com/questions/27870079/isupportincrementalloading-collection-notify-ui-when-loadingmoreitems-is-in-pr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!