9

我想在具有 6 列的 DataGrid 中过滤最多 3000 个项目的 ObservableCollection。用户应该能够以“&&”方式过滤所有 6 列。

我应该使用 LINQ 还是 CollectionView 呢?LINQ 似乎更快地尝试了一些 www 示例。你有什么优点/缺点吗?

更新

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

5 回答 5

3
  • 当您调用 Refresh 时,使用 ICollectionView 会为您提供自动收集更改通知。使用 LINQ,当需要重新运行过滤器以更新 UI 时,您需要触发自己的更改通知。不难,但比仅仅调用 Refresh 需要更多的思考。

  • LINQ 比 ICollectionView 使用的简单是/否过滤更灵活,但是如果您不做复杂的事情,那么这种灵活性实际上并没有任何优势。

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

于 2010-10-06T02:29:30.943 回答
1

对于交互式(DataGrid?)体验,您可能应该使用 CollectionView。对于更面向代码的排序,LINQ。

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

于 2010-10-05T20:35:28.747 回答
1

两者怎么样?Thomas Levesque 围绕ICollectionView.

用法:

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/

于 2014-01-14T16:00:43.430 回答
0

你需要我的ObservableComputations库。使用这个库,您可以像这样编写代码:

ObservableCollection<Material> MaterialList = MaterialListInternal.Filtering(m => 
     String.IsNullOrEmpty(FilterKeywords) 
     || DocumentHelper.ContainsCaseInsensitive(
         material.Keywords, FilterKeywords, StringComparison.CurrentCultureIgnoreCase));

MaterialList 反映了 MaterialListInternal 集合中的所有变化。不要忘记将INotifyPropertyChanged接口的实现添加到 Material 类中,以便 MaterialList 集合反映 material.Keywords 属性的变化。

于 2019-11-19T09:48:30.967 回答
0

由于 Refresh 方法重新创建了整个视图,因此基于视觉复杂性和项目数量确实会有明显的性能差异!!!

于 2018-03-14T15:43:11.350 回答