问题
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