一旦数据被过滤,我如何过滤ICollectionView的分页?

时间:2017-02-21 16:06:10

标签: c# wpf mvvm data-binding

我有一个大数据集,按用户标准使用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;

1 个答案:

答案 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="&lt;" Command="{Binding Previous}"  />
        <Button DockPanel.Dock="Right" Content="&gt;" Command="{Binding Next}"/>
        <ListView ItemsSource="{Binding PagingCollectionView}"/>

    </DockPanel>
</Window>

注意:此代码不是生产代码,只是一个显示所需流程的示例,它不健全