As mentioned in this, you can take code from Silverlight and use that in WPF.
Own CollectionView for paging, sorting and filtering
-
01-04-2022 - |
Question
I've implemented my own CollectionView to bind a collection of data to a DataGrid in WPF.
The main goal was the pagination, which is working quite well. I've written the following C# code:
public class SchemesCollectionView : CollectionView
{
private readonly IList<Scheme> innerList;
private readonly int itemsPerPage;
private int currentPage = 1;
public SchemesCollectionView(IList<Scheme> source, int itemsPerPage)
: base(source)
{
innerList = source;
this.itemsPerPage = itemsPerPage;
}
public override int Count
{
get { return itemsPerPage; }
}
public int CurrentPage
{
get { return currentPage; }
set
{
currentPage = value;
OnPropertyChanged(new PropertyChangedEventArgs("CurrentPage"));
OnPropertyChanged(new PropertyChangedEventArgs("FirstItemNumber"));
OnPropertyChanged(new PropertyChangedEventArgs("LastItemNumber"));
}
}
public int ItemsPerPage { get { return this.itemsPerPage; } }
public int PageCount
{
get
{
return (this.innerList.Count() + this.itemsPerPage - 1)
/ this.itemsPerPage;
}
}
public int LastItemNumber
{
get
{
var end = currentPage * itemsPerPage - 1;
end = (end > innerList.Count()) ? innerList.Count() : end;
return end + 1;
}
}
public int StartIndex
{
get { return (currentPage - 1) * itemsPerPage; }
}
public int FirstItemNumber
{
get { return ((currentPage - 1) * itemsPerPage) + 1; }
}
public override object GetItemAt(int index)
{
var offset = index % (ItemsPerPage);
var position = StartIndex + offset;
if (position >= innerList.Count)
{
position = innerList.Count - 1;
}
return innerList[position];
}
public void MoveToNextPage()
{
if (CurrentPage < PageCount)
{
CurrentPage += 1;
}
Refresh();
}
public void MoveToPreviousPage()
{
if (CurrentPage > 1)
{
CurrentPage -= 1;
}
Refresh();
}
public void MoveToFirstPage()
{
CurrentPage = 1;
Refresh();
}
public void MoveToLastPage()
{
CurrentPage = PageCount;
Refresh();
}
}
As mentioned, the pagination works very well. But I can't get the filtering and sorting work. When I add a custom filter to the Filter property, It gets completely ignored. The same with the sorting. I can see the arrows on the column headers after I clicked them, but the different sorting is not reflected within the DataGrid.
What I'm missing here? Hope someone can help.
Solution
OTHER TIPS
Here is a solution for filtering and paging using only the CollectionView class.
You just need to set the current page index and max items per page to fits your needs.
// obtenir la CollectionView
ICollectionView cvCollectionView = CollectionViewSource.GetDefaultView(this.Suivis);
if (cvCollectionView == null)
return;
// filtrer ... exemple pour tests DI-2015-05105-0
cvCollectionView.Filter = p_oObject => { return true; /* use your own filter */ };
// page configuration
int iMaxItemPerPage = 2;
int iCurrentPage = 0;
int iStartIndex = iCurrentPage * iMaxItemPerPage;
// déterminer les objects "de la page"
int iCurrentIndex = 0;
HashSet<object> hsObjectsInPage = new HashSet<object>();
foreach (object oObject in cvCollectionView)
{
// break if MaxItemCount is reached
if (hsObjectsInPage.Count > iMaxItemPerPage)
break;
// add if StartIndex is reached
if (iCurrentIndex >= iStartIndex)
hsObjectsInPage.Add(oObject);
// increment
iCurrentIndex++;
}
// refilter
cvCollectionView.Filter = p_oObject =>
{
return cvCollectionView.Contains(p_oObject) && hsObjectsInPage.Contains(p_oObject);
};