C# ISupportIncrementalLoading集合-正在加载更多项时通知UI

C# 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中做这件事,我觉得这是一个

我已经在我的应用程序中创建了一个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。