定制Paginate

时间:2016-11-30 15:30:12

标签: c# wpf .net-4.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

    }

}

创建一个集合(在viewModel中)

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

删除元素(在viewModel中)

Articles.Remove(selectedArticle);

1 个答案:

答案 0 :(得分: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]);
                }
            }
        }));
    }));
}