Wpf 使用LINQ vs CollectionView筛选集合
我想在一个有6列的DataGrid中过滤一个最多3000项的ObservableCollection。用户应该能够以“&&”的方式筛选所有6列 我应该使用LINQ还是CollectionView?LINQ似乎更快地尝试了一些www样本。你有什么赞成/反对意见吗 更新:Wpf 使用LINQ vs CollectionView筛选集合,wpf,linq,datagrid,filter,nscollectionview,Wpf,Linq,Datagrid,Filter,Nscollectionview,我想在一个有6列的DataGrid中过滤一个最多3000项的ObservableCollection。用户应该能够以“&&”的方式筛选所有6列 我应该使用LINQ还是CollectionView?LINQ似乎更快地尝试了一些www样本。你有什么赞成/反对意见吗 更新: private ObservableCollection<Material> _materialList; private ObservableCollection<Material> _m
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");
}
}
private observeCollection\u materialList;
私人可观察收集材料内部;
公共材料浏览器列表视图模型()
{
_材料内部=新的可观察收集();
对于(int i=0;i<2222;i++)
{
var mat=新材料()
{
Schoolday=DateTime.Now.Date,
周期=i,
DocumentName=“Excel工作表”+i,
关键词=“财务预算报告”,
SchoolclassCode=“1”,
};
_材料内部添加(垫);
var mat1=新材料()
{
Schoolday=DateTime.Now.Date,
周期=i,
DocumentName=“Word Doc”+i,
关键词=“经济统计报告”,
SchoolclassCode=“2”,
};
_材料内部添加(材料1);
}
MaterialList=CollectionViewSource.GetDefaultView(MaterialListInternal);
MaterialList.Filter=新谓词(containsFilter);
}
公共bool containsFilter(对象项)
{
if(String.IsNullOrEmpty(FilterKeywords))
返回true;
材料=作为材料的项目;
if(DocumentHelper.ContainsCaseInsensitive(material.Keywords、FilterKeywords、StringComparison.CurrentCultureIgnorCase))
返回true;
其他的
返回false;
}
私有字符串\u过滤器关键字;
公共字符串筛选器关键字
{
获取{return\u filterKeywords;}
设置
{
if(_filterKeywords==值)
返回;
_filterKeywords=值;
this.RaisePropertyChanged(“FilterKeywords”);
材料列表刷新();
}
}
公共ICollectionView材质列表{get;set;}
公共可见收集材料内部
{
获取{return\u materialListInternal;}
设置
{
_材料内部=数值;
本.RaisePropertyChanged(“材料专家”);
}
}
对于交互式(DataGrid?)体验,您可能应该使用CollectionView。对于更面向代码的排序,LINQ
对于最多3000个项目,速度不应该是UI中的一个(主要)因素。- 使用ICollectionView可以在调用Refresh时自动发出集合更改通知。使用LINQ,当需要重新运行过滤器以更新UI时,您需要触发自己的更改通知。不难,但需要比调用Refresh更多的思考
- LINQ比ICollectionView使用的简单的是/否过滤更灵活,但是如果您不做复杂的事情,那么这种灵活性实际上没有任何优势
- 正如Henk所说,UI中不应该有明显的性能差异
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();
i无数人;
//使用查询理解
变量查询=
来自people.ShapeView()中的p
其中p.年龄>=18
orderby p.LastName,p.FirstName
p组按p.国家分组;
query.Apply();
//使用扩展方法
people.ShapeView()
.其中(p=>p.年龄>=18)
.OrderBy(p=>p.LastName)
.ThenBy(p=>p.FirstName)
.Apply();
代码:
公共静态类集合ViewShaper
{
公共静态集合ViewShapper ShapeView(此IEnumerable源)
{
var view=CollectionViewSource.GetDefaultView(源);
返回新集合ViewShaper(视图);
}
公共静态集合视图形状(此ICollectionView视图)
{
返回新集合ViewShaper(视图);
}
}
公共类集合ViewShaper
{
私有只读ICollectionView\u视图;
私有谓词过滤器;
私有只读列表_sortddescriptions=new List();
私有只读列表_groupDescriptions=新列表();
公共集合视图形状器(ICollectionView视图)
{
如果(视图==null)
抛出新的异常(“视图”);
_视图=视图;
_filter=view.filter;
_sortDescriptions=view.sortDescriptions.ToList();
_groupDescriptions=view.groupDescriptions.ToList();
}
公开无效申请()
{
使用(_view.DeferRefresh())
{
_view.Filter=\u Filter;
_view.SortDescriptions.Clear();
foreach(分类说明中的var s)
{
_view.SortDescriptions.Add(s);
}
_view.GroupDescriptions.Clear();
foreach(组描述中的变量g)
{
_view.GroupDescriptions.Add(g);
}
}
}
公共集合ViewShaper ClearGrouping()
{
_groupDescriptions.Clear();
归还这个;
}
公共集合ViewShaper ClearSort()
{
_sortDescriptions.Clear();
归还这个;
}
公共集合ViewShaper ClearFilter()
{
_filter=null;
归还这个;
}
公共集合ViewShaper ClearAll()
{
_filter=null;
_sortDescriptions.Clear();
_groupDescriptions.Clear();
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());
}
}