Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 基于单元格值筛选datagridview中的对象列表_C#_.net_Winforms_Linq_Reflection - Fatal编程技术网

C# 基于单元格值筛选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

我目前还不确定让过滤器在datagridview上正常工作的最佳方式,datagridview的数据源设置为对象列表。

因此,给定一个对象:

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