2017-02-21 59 views
0

У меня есть большой набор данных, отфильтрованный по пользовательским критериям с помощью ICollectionView, и я хотел бы выполнить разбиение на данные из квалифицированного результата.Как фильтровать для разбивки на страницы 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

Я предполагаю, что Ваш, пейджинг похож на это http://stackoverflow.com/questions/784726/how-can-i-paginate-a-wpf-datagrid, и в этом случае вам просто нужно будет изменить 'this._innerList.Count', чтобы подсчитать, где проходит фильтр, тогда вам не нужно складывать свои views – MikeT

+0

См. пример ниже – MikeT

+0

Я оцениваю, подходит ли этот пример для моего случая. Большое спасибо! Я дам некоторую обратную связь! – arturn

ответ

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> 

Примечание: этот код не является производство код только один пример, чтобы показать, требуется процесс, это не надежный

+0

Свойство «FilteredCollection» фильтрует всю коллекцию каждый раз, когда мы обращаемся к ней, не так ли? – arturn

+0

да, вы могли бы повысить эффективность за счет кэширования результатов, просто убедитесь, что вы очистили кеш при обновлении – MikeT

+0

его тоже стоит отметить, что теперь в представлении коллекции принимается IEnumerable not ILsit – MikeT