2010-10-05 58 views
8

我想筛选具有6列的DataGrid中的最大3000个项目的ObservableCollection。用户应该能够过滤“& &” - 全部6列。使用LINQ筛选集合与CollectionView

我应该使用LINQ还是CollectionView? LINQ似乎更快尝试一些www样本。你有没有任何专业/职业?

UPDATE

private ObservableCollection<Material> _materialList; 
     private ObservableCollection<Material> _materialListInternal; 

     public MaterialBrowserListViewModel() 
     {   
       _materialListInternal = new ObservableCollection<Material>();   

      for (int i = 0; i < 2222; i++) 
      { 
       var mat = new Material() 
       { 
        Schoolday = DateTime.Now.Date, 
        Period = i, 
        DocumentName = "Excel Sheet" + i, 
        Keywords = "financial budget report", 
        SchoolclassCode = "1", 
       }; 
       _materialListInternal.Add(mat); 
       var mat1 = new Material() 
       { 
        Schoolday = DateTime.Now.Date, 
        Period = i, 
        DocumentName = "Word Doc" + i, 
        Keywords = "Economical staticstics report", 
        SchoolclassCode = "2", 
       }; 
       _materialListInternal.Add(mat1); 
      } 

      MaterialList = CollectionViewSource.GetDefaultView(MaterialListInternal); 
      MaterialList.Filter = new Predicate<object>(ContainsInFilter); 
     }  

     public bool ContainsInFilter(object item) 
     { 
      if (String.IsNullOrEmpty(FilterKeywords)) 
       return true; 

      Material material = item as Material; 
      if (DocumentHelper.ContainsCaseInsensitive(material.Keywords,FilterKeywords,StringComparison.CurrentCultureIgnoreCase))   
       return true;   
      else   
       return false;      
     } 

     private string _filterKeywords; 
     public string FilterKeywords 
     { 
      get { return _filterKeywords; } 
      set 
      { 
       if (_filterKeywords == value) 
        return; 

       _filterKeywords = value; 
       this.RaisePropertyChanged("FilterKeywords"); 
       MaterialList.Refresh();    
      } 
     } 

     public ICollectionView MaterialList { get; set; } 

     public ObservableCollection<Material> MaterialListInternal 
     { 
      get { return _materialListInternal; } 
      set 
      { 
       _materialListInternal = value; 
       this.RaisePropertyChanged("MaterialList"); 
      } 
     } 

回答

1

对于您应该probabaly使用的CollectionView的互动(DataGrid中?)的经验。对于更多的面向代码的排序,LINQ。

对于最多3000个项目,速度不应该是UI中的(主要)因素。

+0

我使用的是CollectionViewSource过滤此刻只是一列。你知道为什么只有在将.Refresh()方法放在下面的属性中时才更新集合? private string _filterKeywords public string FilterKeywords { get {return _filterKeywords; } set { if(_filterKeywords == value) return; _filterKeywords = value; this.RaisePropertyChanged(“FilterKeywords”); MaterialList.Refresh(); } } – Elisabeth 2010-10-05 21:17:16

+0

“你知道为什么......” - 不,但如果你将代码添加到我可能能够阅读的问题中。 – 2010-10-05 21:21:01

+0

好的Henk我发布了所有重要的代码!晚安 ;-) – Elisabeth 2010-10-05 21:26:42

3
  • 使用ICollectionView可为您在调用刷新时自动收集已更改的通知。使用LINQ时,需要重新运行过滤器以更新UI时,需要激发自己的更改通知。不难,但需要多一点思考,而不仅仅是调用Refresh。

  • LINQ更灵活,ICollectionView使用简单的yes/no过滤,但如果你没有做一些复杂的事情,那么这种灵活性没有任何优势。

  • 正如Henk所说,UI中不应该有明显的性能差异。

1

两者如何? Thomas Levesque围绕ICollectionView构建了一个启用LINQ的包装。

用法:

IEnumerable<Person> people; 

// Using query comprehension 
var query = 
    from p in people.ShapeView() 
    where p.Age >= 18 
    orderby p.LastName, p.FirstName 
    group p by p.Country; 

query.Apply(); 

// Using extension methods 
people.ShapeView() 
     .Where(p => p.Age >= 18) 
     .OrderBy(p => p.LastName) 
     .ThenBy(p => p.FirstName) 
     .Apply(); 

代码:

public static class CollectionViewShaper 
{ 
    public static CollectionViewShaper<TSource> ShapeView<TSource>(this IEnumerable<TSource> source) 
    { 
     var view = CollectionViewSource.GetDefaultView(source); 
     return new CollectionViewShaper<TSource>(view); 
    } 

    public static CollectionViewShaper<TSource> Shape<TSource>(this ICollectionView view) 
    { 
     return new CollectionViewShaper<TSource>(view); 
    } 
} 

public class CollectionViewShaper<TSource> 
{ 
    private readonly ICollectionView _view; 
    private Predicate<object> _filter; 
    private readonly List<SortDescription> _sortDescriptions = new List<SortDescription>(); 
    private readonly List<GroupDescription> _groupDescriptions = new List<GroupDescription>(); 

    public CollectionViewShaper(ICollectionView view) 
    { 
     if (view == null) 
      throw new ArgumentNullException("view"); 
     _view = view; 
     _filter = view.Filter; 
     _sortDescriptions = view.SortDescriptions.ToList(); 
     _groupDescriptions = view.GroupDescriptions.ToList(); 
    } 

    public void Apply() 
    { 
     using (_view.DeferRefresh()) 
     { 
      _view.Filter = _filter; 
      _view.SortDescriptions.Clear(); 
      foreach (var s in _sortDescriptions) 
      { 
       _view.SortDescriptions.Add(s); 
      } 
      _view.GroupDescriptions.Clear(); 
      foreach (var g in _groupDescriptions) 
      { 
       _view.GroupDescriptions.Add(g); 
      } 
     } 
    } 

    public CollectionViewShaper<TSource> ClearGrouping() 
    { 
     _groupDescriptions.Clear(); 
     return this; 
    } 

    public CollectionViewShaper<TSource> ClearSort() 
    { 
     _sortDescriptions.Clear(); 
     return this; 
    } 

    public CollectionViewShaper<TSource> ClearFilter() 
    { 
     _filter = null; 
     return this; 
    } 

    public CollectionViewShaper<TSource> ClearAll() 
    { 
     _filter = null; 
     _sortDescriptions.Clear(); 
     _groupDescriptions.Clear(); 
     return this; 
    } 

    public CollectionViewShaper<TSource> Where(Func<TSource, bool> predicate) 
    { 
     _filter = o => predicate((TSource)o); 
     return this; 
    } 

    public CollectionViewShaper<TSource> OrderBy<TKey>(Expression<Func<TSource, TKey>> keySelector) 
    { 
     return OrderBy(keySelector, true, ListSortDirection.Ascending); 
    } 

    public CollectionViewShaper<TSource> OrderByDescending<TKey>(Expression<Func<TSource, TKey>> keySelector) 
    { 
     return OrderBy(keySelector, true, ListSortDirection.Descending); 
    } 

    public CollectionViewShaper<TSource> ThenBy<TKey>(Expression<Func<TSource, TKey>> keySelector) 
    { 
     return OrderBy(keySelector, false, ListSortDirection.Ascending); 
    } 

    public CollectionViewShaper<TSource> ThenByDescending<TKey>(Expression<Func<TSource, TKey>> keySelector) 
    { 
     return OrderBy(keySelector, false, ListSortDirection.Descending); 
    } 

    private CollectionViewShaper<TSource> OrderBy<TKey>(Expression<Func<TSource, TKey>> keySelector, bool clear, ListSortDirection direction) 
    { 
     string path = GetPropertyPath(keySelector.Body); 
     if (clear) 
      _sortDescriptions.Clear(); 
     _sortDescriptions.Add(new SortDescription(path, direction)); 
     return this; 
    } 

    public CollectionViewShaper<TSource> GroupBy<TKey>(Expression<Func<TSource, TKey>> keySelector) 
    { 
     string path = GetPropertyPath(keySelector.Body); 
     _groupDescriptions.Add(new PropertyGroupDescription(path)); 
     return this; 
    } 

    private static string GetPropertyPath(Expression expression) 
    { 
     var names = new Stack<string>(); 
     var expr = expression; 
     while (expr != null && !(expr is ParameterExpression) && !(expr is ConstantExpression)) 
     { 
      var memberExpr = expr as MemberExpression; 
      if (memberExpr == null) 
       throw new ArgumentException("The selector body must contain only property or field access expressions"); 
      names.Push(memberExpr.Member.Name); 
      expr = memberExpr.Expression; 
     } 
     return String.Join(".", names.ToArray()); 
    } 
} 

信用: http://www.thomaslevesque.com/2011/11/30/wpf-using-linq-to-shape-data-in-a-collectionview/