C# 基于单元格值筛选datagridview中的对象列表
我目前还不确定让过滤器在datagridview上正常工作的最佳方式,datagridview的数据源设置为对象列表。C# 基于单元格值筛选datagridview中的对象列表,c#,.net,winforms,linq,reflection,C#,.net,Winforms,Linq,Reflection,我目前还不确定让过滤器在datagridview上正常工作的最佳方式,datagridview的数据源设置为对象列表。 因此,给定一个对象: public class DepositAccountBill { #region Properties public int AccountBillID { get; set; } public int AccountID { get; set; } public strin
因此,给定一个对象:
public class DepositAccountBill
{
#region Properties
public int AccountBillID { get; set; }
public int AccountID { get; set; }
public string AccountNumber { get; set; }
public string ControlNumber { get; set; }
public DateTime BillDate { get; set; }
public decimal DepositAmount { get; set; }
}
我有一个datagridview表,大致如下所示:
Account Number | Control Number | Bill Date | Deposit Amount
==================================================================
123456 | AJA1234367 | 5/21/2018 | 12.99
123456 | PSA1234367 | 5/21/2018 | 5.77
567332 | HBA1234367 | 5/21/2018 | 1255.99
769843 | AJA1234367 | 5/21/2018 | 12.99
var filterList = collection.Where(r => r.AccountNumber == clickedCell.Value);
所以当点击一个单元格时。假设第一列上的第一个单元格。如果我右键单击一个单元格并在一个上下文菜单中选择一个选项,该选项显示filter,那么我需要显示datagridview表,其中只包含具有相同帐号的行。在本例中,它将是第1行和第2行。
为了做到这一点,我必须访问datagridview表中填充了DepostAccountBill的对象。因此,我需要做的是查看,我正在查看的列具有所选单元格的值
因此,在我的方法中,我迄今为止一直在尝试,但没有任何结果:
var collection = (List<DepositAccountBill>)dataGridView1.DataSource;
var filterList = collection.Where ( q => (collection.Select(r => GetPropValue(r, dataGridView1.Columns[clickedCell.ColumnIndex].DataPropertyName))) == (clickedCell.Value);
dataGridView1.DataSource = filterList.ToList();
public object GetPropValue(object obj, string propName)
{
return obj.GetType().GetProperty(propName).GetValue(obj, null);
}
唯一的问题是
r。AccountNumber
取决于所选列的数据属性。程序不知道基于选定单元格上的单击事件的数据属性是什么。这就是为什么我认为反射可能是必要的。我想您知道如何使用列的DataPropertyName
属性提取属性名称,以及如何从单元格的value
属性获取值
在回答中,我将重点介绍如何对具有属性名称和值的列表执行动态筛选,就像使用时一样。其中(x=>x.PropertyName==Value)
为此,您可以选择几个选项,包括:
动态Linq库
在运行时动态创建表达式
使用包含每个属性所需条件的词典
简单地使用if/else
我将分享有关上述解决方案的更多详细信息,您可以选择其中之一
注意:如果答案太长,最简单、最明显的答案可能是第四个选项
选项1-动态Linq库
作为一个选项,您可以将System.Linq.Dynamic
引用添加到项目中,然后在使用System.Linq.Dynamic
命名空间后,通过将条件作为string
传递,您将能够在IEnumerable
或IQueryable
上创建动态查询,例如:
var list = db.Products.ToList();
var result = list.Where("Name = @0", "product1").ToList();
这样,您就可以在查询中动态地使用列数据属性名称和列值。要了解有关dynamic linq的更多信息,请参阅以下参考资料:
- 对于
System.Linq.Dynamic
。您只需在软件包管理器控制台中使用以下命令即可安装软件包:install package System.Linq.Dynamic
- 对于
System.Linq.Dynamic
-
关于动态LINQ(第1部分:使用LINQ动态查询库)
选项2-在运行时创建Lambda表达式
作为另一个选项,您可以在运行时创建lambda表达式,并将其与Where
方法一起使用。例如,可以创建以下方法:
//Creates x=>x.Something == value
public Expression<Func<T, bool>> EqualCriteria<T>(string propertyName, object value)
{
var property = typeof(T).GetProperty(propertyName);
var x = Expression.Parameter(typeof(T), "x");
var propertyExpression = Expression.Property(x, property.Name);
var valueExpression = Expression.Convert(Expression.Constant(value),
property.PropertyType);
var criteria = Expression.Equal(propertyExpression, valueExpression);
var lambda = Expression.Lambda<Func<T, bool>>(criteria, x);
return lambda;
}
选项4-使用if/else
作为另一个选项,您可以简单地使用if/else条件。例如,假设您在对象变量中有值,在字符串变量中有属性名,那么您可以编写:
var list = db.Products.ToList();
var result = list.ToList();
if (propertyName == "Id")
{
result = result.Where(x=>x.Id == (int)value).ToList();
}
else if (propertyName == "Name")
{
result = result.Where(x=>x.Name == (string)value).ToList();
}
您在什么情况下处理上述代码?我正在处理所选单元格上的右键单击事件(CellMouseUp)中的事件。
var criterias = new Dictionary<string, Func<Product, object, bool>>() {
{ "Id" , (p,v)=>p.Id.Equals(v) },
{ "Name" , (p,v)=>p.Name.Equals(v) }
};
var list = db.Products.ToList();
var result = list.Where(x => criterias["Name"](x, "product1")).ToList();
var list = db.Products.ToList();
var result = list.ToList();
if (propertyName == "Id")
{
result = result.Where(x=>x.Id == (int)value).ToList();
}
else if (propertyName == "Name")
{
result = result.Where(x=>x.Name == (string)value).ToList();
}