2015-01-09 46 views
1

我已經在我的應用程序中創建了一個IncrementalLoadingCollection類,該類實現了ISupportIncrementalLoading並從ObservableCollection< T >繼承。ISupportIncrementalLoading集合 - 當正在進行LoadingMoreItems時通知UI

它工作正常,項目已加載,但我想在應用程序的Status Bar上顯示一條消息,指出有一些工作正在進行中。

實現這個目標的好方法是什麼?

由於LoadMoreItemsAsync在滾動列表時被內部調用,所以我無法訪問那部分代碼來更新Status Bar。現在,我正在做這LoadMoreItemsAsync,我發現它是一種可怕的方法,但我目前找不到更好的...

任何建議,非常感謝。

回答

4

那麼你可以,例如:從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(); 
    } 
} 

如何使用它?在您的視圖模型:

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不appropiate地方UI相關的操作看一看一些通訊機制(如MVVM Light Messenger,註冊代碼隱藏消息,並在LoadMoreItemsStarted處理程序發送該消息)

+1

使用這種方法事件絕對是偉大的,我喜歡它!我已經在使用調度員回覆UI的消息,但由於可怕的耦合,我完全不滿意。如果只有我可以多次投票這個答案:)非常感謝! – VasileF 2015-01-09 23:22:38

+0

似乎雖然通知只發生一次,在第一個電話...我已經做了一個編輯。處理程序中的代碼是在斷點被執行時執行的,但UI上沒有顯示任何內容...... – VasileF 2015-01-09 23:48:01

+0

@VasileF與IncrementalObservableCollection無關錯誤 - 調用OnCompleted時調用「StatusBar.HideAsync」(根據您的代碼)這意味着StatusBar將被關閉,直到您調用「StatusBar.ShowAsync」。所以你需要調用:await statusBar.ShowAsync();在顯示進度指示器 – fex 2015-01-09 23:55:35

相關問題