2016-11-30 112 views
0

我发现此代码分页集合。它适用于我需要的内容,但我希望能够在另一个线程中进行分页,因为如果每页中的项目数很大,则界面会暂时冻结。自定义分页

“RecalculateThePageItems”方法负责创建每个页面(创建集合时,删除记录时和更改页面时)。一些帮助?非常感谢你!

using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.ComponentModel; 

namespace WPF.Utilidades 
{ 
    /// <summary> 
    /// This class represents a single Page collection, but have the entire items available inside 
    /// </summary> 

    public class PaginatedObservableCollection<T> : ObservableCollection<T> 
    { 
     #region Properties 

     private const int FistPage = 1; 

     private readonly List<T> _originalCollection; 

     #region Commands 

     public void ExecuteNextPage() 
     { 
      CurrentPage++; 
      OnPropertyChanged(new PropertyChangedEventArgs("ItemsFrom")); 
      OnPropertyChanged(new PropertyChangedEventArgs("ItemsTo")); 
     } 

     public bool CanExecuteNextPage() 
     { 
      return TotalPages > CurrentPage; 
     } 

     public void ExecutePreviousPage() 
     { 
      CurrentPage--; 
      OnPropertyChanged(new PropertyChangedEventArgs("ItemsFrom")); 
      OnPropertyChanged(new PropertyChangedEventArgs("ItemsTo")); 
     } 

     public bool CanExecutePreviousPage() 
     { 
      return CurrentPage > FistPage; 
     } 

     public void ExecuteFirstPage() 
     { 
      CurrentPage = FistPage; 
      OnPropertyChanged(new PropertyChangedEventArgs("ItemsFrom")); 
      OnPropertyChanged(new PropertyChangedEventArgs("ItemsTo")); 
     } 

     public bool CanExecuteFirstPage() 
     { 
      return TotalPages > 0 && CurrentPage != FistPage; 
     } 

     public void ExecuteLastPage() 
     { 
      CurrentPage = TotalPages; 
      OnPropertyChanged(new PropertyChangedEventArgs("ItemsFrom")); 
      OnPropertyChanged(new PropertyChangedEventArgs("ItemsTo")); 
     } 

     public bool CanExecuteLastPage() 
     { 
      return CurrentPage != TotalPages; 
     } 

     #endregion 

     private int _itemsPerPage; 

     private int ItemsPerPage 
     { 
      get { return _itemsPerPage; } 
      set 
      { 
       if (value > 0) 
       { 
        _itemsPerPage = value; 
        RecalculateItemsPerPage(); 
        OnPropertyChanged(new PropertyChangedEventArgs("ItemsPerPage")); 
       } 
      } 
     } 

     private int _currentPage; 

     public int CurrentPage 
     { 
      get { return _currentPage; } 
      set 
      { 
       if (value > 0) 
       { 
        _currentPage = value; 
        RecalculateItemsPerPage(); 
        OnPropertyChanged(new PropertyChangedEventArgs("CurrentPage")); 
       } 
      } 
     } 

     private int _totalPages; 

     public int TotalPages 
     { 
      get { return _totalPages; } 
      set 
      { 
       if (_totalPages != value) 
       { 
        if (value < _currentPage) 
        { 
         CurrentPage--; 
        } 
        _totalPages = value; 
        OnPropertyChanged(new PropertyChangedEventArgs("TotalPages")); 
       } 
      } 
     } 

     private int _totalItems; 

     public int TotalItems 
     { 
      get { return _originalCollection.Count; } 
      set 
      { 
       if (_totalItems != value) 
       { 
        _totalItems = value; 
        OnPropertyChanged(new PropertyChangedEventArgs("TotalItems")); 
       } 
      } 
     } 

     private int _itemsFrom; 

     public int ItemsFrom 
     { 
      get { return _originalCollection.Count > 0 ? (CurrentPage - 1) * ItemsPerPage + 1 : 0; } 
      set 
      { 
       if (_itemsFrom != value) 
       { 
        _itemsFrom = value; 
        OnPropertyChanged(new PropertyChangedEventArgs("ItemsFrom")); 
       } 
      } 
     } 

     private int _itemsTo; 

     public int ItemsTo 
     { 
      get { return ItemsFrom == 0 ? 0 : ItemsFrom + ItemsPerPage - 1 < TotalItems ? ItemsFrom + ItemsPerPage - 1 : TotalItems; } 
      set 
      { 
       if (_itemsTo != value) 
       { 
        _itemsTo = value; 
        OnPropertyChanged(new PropertyChangedEventArgs("ItemsTo")); 
       } 
      } 
     } 

     #endregion 

     #region Constructor 
     public PaginatedObservableCollection(IEnumerable<T> collection) 
     { 
      _originalCollection = new List<T>(collection); 
      _currentPage = 1; 
      _itemsPerPage = 10; 
      CalculateTotalPages(); 
      RecalculateItemsPerPage(); 
     } 

     public PaginatedObservableCollection(int itemsPerPage) 
     { 
      _itemsPerPage = itemsPerPage <= 0 ? 1 : itemsPerPage; 
      _originalCollection = new List<T>(); 
     } 
     public PaginatedObservableCollection() 
     { 
      _originalCollection = new List<T>(); 
     } 
     #endregion 

     #region Private 
     private void RecalculateItemsPerPage() 
     { 
      Clear(); 

      var startIndex = _currentPage * _itemsPerPage - _itemsPerPage; 

      for (var i = startIndex; i < startIndex + _itemsPerPage; i++) 
      { 
       if (_originalCollection.Count > i) 
       { 
        base.InsertItem(i - startIndex, _originalCollection[i]); 
       } 
      } 

     } 

     private void CalculateTotalPages() 
     { 
      var itemCount = _originalCollection.Count; 
      var thisMod = itemCount % _itemsPerPage; 
      var thisDiv = itemCount/_itemsPerPage; 

      TotalPages = thisMod == 0 ? thisDiv : thisDiv + 1; 
     } 

     #endregion 

     #region Overrides 

     protected override void InsertItem(int index, T item) 
     { 
      var startIndex = _currentPage * _itemsPerPage; 
      var endIndex = startIndex + _itemsPerPage; 

      //Check if the Index is with in the current Page then add to the collection as bellow. And add to the originalCollection also 
      if ((index >= startIndex) && (index < endIndex)) 
      { 
       base.InsertItem(index - startIndex, item); 

       if (Count > _itemsPerPage) 
       { 
        base.RemoveItem(endIndex); 
       } 
      } 

      if (index >= Count) 
      { 
       _originalCollection.Add(item); 
      } 
      else 
      { 
       _originalCollection.Insert(index, item); 
      } 
     } 

     protected override void RemoveItem(int index) 
     { 
      var startIndex = _currentPage * _itemsPerPage; 
      var endIndex = startIndex + _itemsPerPage; 

      //Check if the Index is with in the current Page range then remove from the collection as bellow. And remove from the originalCollection also 
      if ((index >= startIndex) && (index < endIndex)) 
      { 
       RemoveAt(index - startIndex); 

       if (Count <= _itemsPerPage) 
       { 
        base.InsertItem(endIndex - 1, _originalCollection[index + 1]); 
       } 
      } 

      _originalCollection.RemoveAt(index + (_currentPage - FistPage) * _itemsPerPage); 

      CalculateTotalPages(); 

      RecalculateItemsPerPage(); 
     } 

     #endregion 

    } 

} 

创建集合(在视图模型)

Articles = 
      await 
       TaskEx.Run(
        () => new PaginatedObservableCollection<Article>(_articleService.GetList())); 

删除元素(在视图模型)

Articles.Remove(selectedArticle); 

回答

1

更新您的Recalculate方法使用async

private async void RecalculateItemsPerPage() 
{ 
    await Task.Run(new Action(() => 
    { 
     Application.Current.Dispatcher.BeginInvoke(new Action(() => 
     { 
      Clear(); 

      var startIndex = _currentPage * _itemsPerPage - _itemsPerPage; 

      for (var i = startIndex; i < startIndex + _itemsPerPage; i++) 
      { 
       if (_originalCollection.Count > i) 
       { 
        base.InsertItem(i - startIndex, _originalCollection[i]); 
       } 
      } 
     })); 
    })); 
} 
+0

Thx寻求帮助!我有一个“问题”,其中“使用”包含“Application.Current.Dispatcher.InvokeAsync”即时通讯使用NET 4.0。 – avechuche

+0

@avechuche查看更新。请注意对'BeginInvoke'的更改 –

+0

再次感谢,我已经尝试过(还有更多),但它不起作用。这是使用BeginInvoke时的错误 ---'DispatcherOperation'不包含'GetAwaiter'的定义,并且'AwaitExtensions.GetAwaiter(Task)'扩展方法的最佳开销需要'Task' – avechuche