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
处理程序中)
我在我的应用程序中创建了一个 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
处理程序中)