C# ISupportIncrementalLoading集合-正在加载更多项时通知UI
我已经在我的应用程序中创建了一个IncrementalLoadingCollection类,它实现了ISupportIncrementalLoading并从ObservaleCollectionC# ISupportIncrementalLoading集合-正在加载更多项时通知UI,c#,windows-runtime,windows-phone-8.1,message,statusbar,C#,Windows Runtime,Windows Phone 8.1,Message,Statusbar,我已经在我的应用程序中创建了一个IncrementalLoadingCollection类,它实现了ISupportIncrementalLoading并从ObservaleCollection继承 它工作正常,项目已加载,但我想在应用程序的状态栏上显示一条消息,表示有一些工作正在进行中 实现这一目标的好方法是什么 由于在滚动列表时会在内部调用LoadMoreItemsAsync,因此我无法访问该部分以获得更新状态栏的代码。现在,我在LoadMoreItemsAsync中做这件事,我觉得这是一个
非常感谢您的建议。您可以这样做,例如:继承ObservableCollection并实现iSupportIncrementLoading:
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线程。如果不使用Dispatcher,则无法从UI线程以外的线程调用与UI相关的方法
如果您觉得ViewModel不适合用于UI相关操作,请查看一些消息传递机制,如MVVM Light Messenger,在代码隐藏中注册消息,并在LoadMoreItemsStartedHandler中发送此消息。例如,您可以从ObservableCollection继承并实现ISupportIncrementLoading,如下所示:
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线程。如果不使用Dispatcher,则无法从UI线程以外的线程调用与UI相关的方法
如果您觉得ViewModel不适合进行与UI相关的操作,请查看一些消息传递机制,如MVVM Light Messenger,在代码隐藏中注册消息,并在LoadMoreItems启动处理程序中发送此消息这种使用事件的方法绝对很棒,我喜欢它!我已经在使用dispatcher返回UI,返回消息,但由于严重耦合,我一点也不满意。如果我能多次投票给这个答案就好了:非常感谢!似乎通知只在第一次调用时发生一次。。。我做了一个编辑。处理程序中的代码在断点被命中时执行,但UI上没有显示任何与IncrementalObservableCollection无关的错误…@VasileF-OnCompleted时称为StatusBar.HideAsync,根据您的代码调用,这意味着StatusBar将关闭,直到您调用StatusBar.ShowAsync。因此您需要调用:wait statusBar.ShowAsync;在你表现出进步之前indiciator@Vasilef我宁愿在完成的事件处理程序中使用StatusBar.ProgressIndicator.HideAsync。这种使用事件的方法非常棒,我喜欢!我已经在使用dispatcher返回UI,返回消息,但由于严重耦合,我一点也不满意。如果我能多次投票给这个答案就好了:非常感谢!似乎通知只在第一次调用时发生一次。。。我做了一个编辑。处理程序中的代码在断点被命中时执行,但UI上没有显示任何与IncrementalObservableCollection无关的错误…@VasileF-OnCompleted时称为StatusBar.HideAsync,根据您的代码调用,这意味着StatusBar将关闭,直到您调用StatusBar.ShowAsync。因此您需要调用:wait statusBar.ShowAsync;在你表现出进步之前indiciator@Vasilef我宁愿在已完成的事件处理程序中使用StatusBar.ProgressIndicator.HideAsync。