ISupportIncrementalLoading Collection - 在LoadingMoreItems正在进行时通知UI

时间:2015-01-09 22:12:17

标签: c# windows-runtime windows-phone-8.1 message statusbar

我已经在我的应用中创建了一个IncrementalLoadingCollection类,它实现了ISupportIncrementalLoading并继承自ObservableCollection< T >

它工作正常并且项目已加载但我想在应用程序的Status Bar上显示一条消息,表明正在进行一些工作。

实现这一目标的好方法是什么?

由于在滚动列表时会在内部调用LoadMoreItemsAsync,因此我无法访问该部分以提供更新Status Bar的代码。现在,我在LoadMoreItemsAsync这样做,我发现这是一个糟糕的方法,但到目前为止我找不到更好的...

非常感谢任何建议。

1 个答案:

答案 0 :(得分:4)

嗯,你可以举例:从ObservableCollection继承并实现ISupportIncrementalLoading,如下所示:

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

如何使用它?在您的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; }
}

你可能会问为什么我在Dispatcher.RunAsync中使用了IncrementalLoadingObservableCollection - 原因是LoadMoreItemsAsync可能会在另一个主题上运行(不知道),所以你必须发送UI Thread的所有工作(不能使用UI thread以外的线程调用与UI相关的方法,而不使用Dispatcher。)

如果您认为ViewModel不适合与UI相关的操作,请查看一些消息传递机制(如MVVM Light Messenger),在代码隐藏中注册消息并在{{1}中发送此消息处理程序)