我正在尝试构建一个在数据网格中显示唯一值的通用过滤器控件,并允许用户过滤网格中特定列的唯一值。
我喜欢为this question提出的答案,但所有这些都要求您事先了解该属性。我想创建代码OCP compliant并且只有一个方法接受属性名称字符串并在其上应用不同的函数(可能使用反射)。这个问题的最佳解决方案是什么,考虑到我的列(因此要过滤的列名称,如名称,年龄等是动态的)。
具体来说,我试图避免这种切换案例陈述:
switch (listColumn.DisplayMemberPath)
{
case "Name" :
listColumn.Items = GridItems.GroupBy(item => item.Name).Select(item => item.First());
break;
case "Age" :
listColumn.Items = GridItems.GroupBy(item=> item.Age).Select(item => item.First());
break;
// and so on...
}
并有一个像这样的通用方法:
public IEnumerable GetDistinctValues(IEnumerable gridItems, string propertyName)
{
// logic to return the distinct values for the given property name...
}
仅供参考 - 我在ViewModel中的集合是ICollectionView类型(猜测在CollectionView中已经定义了类似于我正在寻找的过滤类型的东西)。
答案 0 :(得分:0)
您可以使用C#的表达式树功能,如下所示。
public static IEnumerable GetDistinctValues<T>(IEnumerable<T> gridItems, string propertyName) where T : class
{
// logic to return the distinct values for the given property name...
var xpre = GetPropertyExpression<T>(typeof(T), propertyName);
return gridItems.GroupBy(item => xpre).Select(item => item.First());
}
private static Func<T, object> GetPropertyExpression<T>(Type type, string propertyName)
{
ParameterExpression parameter = Expression.Parameter(type, "x");
MemberExpression propertyExpr = GetPropertyExpression(parameter, type, propertyName);
if (propertyExpr == null)
return null;
Expression<Func<T, object>> expression = Expression.Lambda<Func<T, object>>(Expression.Convert(propertyExpr, typeof(object)), new ParameterExpression[1] { parameter });
return expression.Compile();
}
private static MemberExpression GetPropertyExpression(Expression param, Type type, string propertyName)
{
var property = type.GetProperty(propertyName);
if (property == null)
{
if (propertyName.Contains("_") || propertyName.Contains("."))
{
var innerProps = propertyName.Split(new char[] { '_', '.' }, 2);
property = type.GetProperty(innerProps[0]);
if (property != null)
{
var pe = Expression.Property(param, property);
return GetPropertyExpression(pe, property.PropertyType, innerProps[1]);
}
else
{
return null;
}
}
}
else
{
return Expression.Property(param, property);
}
return param as MemberExpression;
}
用法:
var lst = new List<Student>();
lst.Add(new Student { Name = "Joe", Age = 23 });
lst.Add(new Student { Name = "John", Age = 28 });
lst.Add(new Student { Name = "Jane", Age = 21 });
lst.Add(new Student { Name = "John", Age = 15 });
var vals = GetDistinctValues(lst, "Name"); // here
答案 1 :(得分:-1)
您可以这样做:
void GetDistinctValues(string aPropName)
{
var props = typeof(A).GetProperties();
// make sure your property exists here, otherwise return
// Something like that should be what you want:
var return_col = gridItems[aPropName].Distinct();
}
public class A {
public int Age{get;set;}
public int Height{get;set;}
}
基本上,确保列/属性存在,然后只需运行一个不同的linq。
关于您的评论,您传入了IEnumerable,因此您可以在其上调用Distinct
:
var nmrbl = Enumerable.Range(1,10).Select (e => e%3);
// nmrbl={ 1 ,2 ,0 ,1 ,2 ,0 ,1 ,2 ,0 ,1}
var dist = nmrbl.Distinct();
// dist = {1,2,0}