2010-10-05 26 views
8

6 sütunlu bir DataGrid içinde bir 3000 max ObservableCollection filtre uygulamak istiyorum. Kullanıcı, tüm 6 sütunu "& &" şeklinde filtrelemeli.LINQ vs CollectionView ile bir koleksiyon filtrele

Bunun için LINQ veya CollectionView kullanmalı mıyım? LINQ, bazı www örneklerini denemekten daha hızlı görünüyordu. Herhangi bir yanlısı var mı?

GÜNCELLEME: Eğer probabaly CollectionView'ın kullanmalıdır interaktif (? DataGrid) deneyimi için

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"); 
      } 
     } 

cevap

1

. Daha kod odaklı bir sıralama için LINQ.

Ve en fazla 3000 öğe ile hız, bir UI'de (büyük) bir faktör olmamalıdır.

+0

. Aşağıdaki özellikte .Refresh() yöntemini yerleştirdiğimde koleksiyonun neden güncelleştirildiğini biliyor musunuz? private string _filterKeywords Genel dizge FilterKeywords { {return _filterKeywords; set { (_filterKeywords == değer) döndürse; _filterKeywords = value; this.RaisePropertyChanged ("FilterKeywords"); MaterialList.Refresh(); } } – Elisabeth

+0

"Nedenini biliyor musun?" - Hayır, ama belki de bu kodu soruyu okuyabilseydim, okuyabiliyordum. –

+0

tamam Henk Tüm önemli kodları yayınladım! iyi geceler ;-) – Elisabeth

3
  • ICollectionView kullanımı, Refresh'i çağırdığınızda otomatik koleksiyon değişiklik bildirimleri verir. LINQ kullanarak, UI'yi güncellemek için filtrenin yeniden çalışması gerektiğinde kendi değişiklik bildirimlerinizi tetiklemeniz gerekir. Zor değil, sadece Refresh'i aramaktan biraz daha düşünmek gerekiyor.

  • LINQ, ICollectionView tarafından kullanılan basit evet/hayır filtrelemenin daha esnektir, ancak karmaşık bir şey yapmıyorsanız, bu esnekliğin hiçbir avantajı yoktur. Henk'in belirttiği gibi, kullanıcı arayüzünde dikkate değer bir performans farkı olmamalıdır.

1

İkisine ne dersiniz? Thomas Levesque, ICollectionView civarında bir LINQ etkin paket oluşturdu.

Kullanımı:

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(); 

Kodu:

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()); 
    } 
} 

Kredisi: Bir CollectionViewSource filtresi anda sadece TEK sütun kullanıyorum http://www.thomaslevesque.com/2011/11/30/wpf-using-linq-to-shape-data-in-a-collectionview/

İlgili konular