我有一个大数据集,按用户标准使用ICollectionView进行过滤,我想从合格的结果中执行数据分页。
我认为我需要ICollectionView用于过滤数据而其他用于分页。这是正确的方法吗?
问题是ICollectionView。源不能是其他ICollectionView。 我尝试了其他一些替代方案但没有成功。
IEnumerable<foo> data;
ICollectionView MyDataFilter;
...
this.MyDataFilter = CollectionViewSource.GetDefaultView(data);
System.Diagnostics.Debug.Assert(this.MyDataFilter.CanFilter);
this.MyDataFilter.Filter = DataViewFilter;
PaginationView = CollectionViewSource.GetDefaultView(this.MyDataFilter);
this.PaginationView.Filter = PaginationViewFilter;
答案 0 :(得分:0)
使用How can I paginate a WPF DataGrid?
中的示例并简单地更改标准以考虑过滤
EG
public class PagingCollectionView : CollectionView
{
private readonly int _itemsPerPage;
private int _currentPage = 1;
public PagingCollectionView(IEnumerable innerList, int itemsPerPage)
: base(innerList)
{
this._itemsPerPage = itemsPerPage;
}
public int FilteredCount
{
get {return FilteredCollection.Count(); }
}
private IEnumerable<object> FilteredCollection => this.SourceCollection.OfType<object>().Where(o=>Filter(o));
public override int Count
{
get
{
if (FilteredCount == 0) return 0;
if (this._currentPage < this.PageCount) // page 1..n-1
{
return this._itemsPerPage;
}
else // page n
{
var itemsLeft = FilteredCount % this._itemsPerPage;
if (0 == itemsLeft)
{
return this._itemsPerPage; // exactly itemsPerPage left
}
else
{
// return the remaining items
return itemsLeft;
}
}
}
}
public int CurrentPage
{
get { return this._currentPage; }
set
{
this._currentPage = value;
this.OnPropertyChanged(new PropertyChangedEventArgs("CurrentPage"));
}
}
public int ItemsPerPage { get { return this._itemsPerPage; } }
public int PageCount
{
get
{
return (FilteredCount + this._itemsPerPage - 1)
/ this._itemsPerPage;
}
}
private int EndIndex
{
get
{
var end = this._currentPage * this._itemsPerPage - 1;
return (end > FilteredCount) ? FilteredCount : end;
}
}
private int StartIndex
{
get { return (this._currentPage - 1) * this._itemsPerPage; }
}
public override object GetItemAt(int index)
{
var offset = index % (this._itemsPerPage);
return this.FilteredCollection.ElementAt(this.StartIndex + offset);
}
public void MoveToNextPage()
{
if (this._currentPage < this.PageCount)
{
this.CurrentPage += 1;
}
this.Refresh();
}
public void MoveToPreviousPage()
{
if (this._currentPage > 1)
{
this.CurrentPage -= 1;
}
this.Refresh();
}
}
演示 VM:
public class VM:BindableBase
{
public VM()
{
PagingCollectionView = new PagingCollectionView(
Enumerable.Range(300, 1000).Select(i => i.ToString("X")),
5);
PagingCollectionView.Filter = (o) => string.IsNullOrWhiteSpace(Filter) || o.ToString().StartsWith(Filter);
Next = new DelegateCommand(PagingCollectionView.MoveToNextPage);
Previous = new DelegateCommand(PagingCollectionView.MoveToPreviousPage );
}
private string _Filter;
public string Filter
{
get { return _Filter; }
set {
if(SetProperty(ref _Filter, value))
PagingCollectionView.Refresh();
}
}
public PagingCollectionView PagingCollectionView { get; set; }
public DelegateCommand Next { get; set; }
public DelegateCommand Previous { get; set; }
}
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:VM x:Name="vm" />
</Window.DataContext>
<DockPanel >
<TextBox DockPanel.Dock="Top" Text="{Binding Filter}"/>
<Button DockPanel.Dock="Left" Content="<" Command="{Binding Previous}" />
<Button DockPanel.Dock="Right" Content=">" Command="{Binding Next}"/>
<ListView ItemsSource="{Binding PagingCollectionView}"/>
</DockPanel>
</Window>
注意:此代码不是生产代码,只是一个显示所需流程的示例,它不健全