ISupportIncrementalLoading 集合 - 在 LoadingMoreItems 进行时通知 UI

ISupportIncrementalLoading Collection - notify UI when LoadingMoreItems is in progress

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

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

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

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

非常感谢任何建议。

好吧,例如:从 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; }
}

您可能会问为什么我在 IncrementalLoadingObservableCollection 中使用了 Dispatcher.RunAsync - 原因是 LoadMoreItemsAsync 可能 运行 在另一个线程上(不知道)所以您必须将所有工作分派给 UI Thread(如果不使用 Dispatcher,则无法从 UI thread 以外的线程调用与 UI 相关的方法)。

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