ISupportIncrementalLoading Collection - 在 LoadingMoreItems 正在进行时通知 UI
Posted
技术标签:
【中文标题】ISupportIncrementalLoading Collection - 在 LoadingMoreItems 正在进行时通知 UI【英文标题】:ISupportIncrementalLoading Collection - notify UI when LoadingMoreItems is in progress 【发布时间】:2015-03-08 08:03:31 【问题描述】:我在我的应用中创建了一个IncrementalLoadingCollection
类,它实现了ISupportIncrementalLoading
并继承自ObservableCollection< T >
。
它工作正常并且项目已加载,但我想在应用程序的Status Bar
上显示一条消息,说明正在进行一些工作。
实现这一目标的好方法是什么?
由于滚动列表时在内部调用LoadMoreItemsAsync
,因此我无法访问该部分以提供更新Status Bar
的代码。现在,我在LoadMoreItemsAsync
中执行此操作,我发现这是一种糟糕的方法,但到目前为止我找不到更好的方法...
非常感谢任何建议。
【问题讨论】:
【参考方案1】:例如,您可以:从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
处理程序中发送此消息)
【讨论】:
这种使用事件的方式非常棒,我喜欢!我已经在使用调度程序返回带有消息的 UI,但由于糟糕的耦合,我一点也不满意。如果我能多次投票这个答案就好了:)非常感谢! 通知似乎只发生一次,在第一次通话时......我已经进行了编辑。处理程序中的代码在断点被命中时执行,但 UI 上没有显示任何内容... @VasileF 这不是与 IncrementalObservableCollection 相关的错误 - 当 OnCompleted 被调用时,“StatusBar.HideAsync”被调用(根据您的代码),这意味着 StatusBar 将被关闭,直到您调用“StatusBar.ShowAsync”。所以你需要调用:await statusBar.ShowAsync();在显示进度指示器之前 @Vasilef 我宁愿在 Completed 事件处理程序中使用 StatusBar.ProgressIndicator.HideAsync。以上是关于ISupportIncrementalLoading Collection - 在 LoadingMoreItems 正在进行时通知 UI的主要内容,如果未能解决你的问题,请参考以下文章