Фильтрация списка объектов в сетке данных по значению ячейки - PullRequest
0 голосов
/ 22 мая 2018

В настоящее время я не уверен в том, как лучше настроить фильтр для работы с сеткой данных, для которой в качестве источника данных задан список объектов.

Имеется объект:

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

У меня есть таблица просмотра данных, которая выглядит примерно так:

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 

Итак, при нажатиина камеру.Скажем, первая ячейка в первом столбце.Если я щелкну правой кнопкой мыши по ячейке и выберу в контекстном меню вариант с надписью filter, мне нужно отобразить таблицу datagridview только со строками с одинаковым номером счета.В этом случае это будут строки 1 и 2. Для этого мне нужно получить доступ к объекту, в котором таблица datagridview заполнена с помощью DepositAccountBill.Итак, что мне нужно сделать, это посмотреть, и столбец, на который я смотрю, имеет значение выбранной ячейки.

Итак, в моем методе я попытался пока безрезультатно:

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

Я не знаю, является ли SELECT правильным методом LINQ для использования здесь, или это вообще возможно.Я хочу использовать WHERE, потому что он захватывает только список объектов, которые соответствуют условию.Примерно так:

var filterList = collection.Where(r => r.AccountNumber == clickedCell.Value); 

Единственная проблема в том, что r.AccountNumber зависит от свойства данных выбранного столбца.Программа не знает, какое свойство данных основано на событии щелчка по выбранной ячейке.Вот почему я думаю, что рефлексия может быть необходима.

1 Ответ

0 голосов
/ 23 мая 2018

Полагаю, вы знаете, как извлечь имя свойства с помощью свойства DataPropertyName столбца, а также как получить значение из свойства Value ячейки.

В ответе я сосредоточусьо том, как выполнить динамическую фильтрацию List<T> с именем свойства и значением , как при использовании .Where(x=>x.PropertyName == Value).

Длядля этого у вас есть несколько вариантов, которые вы можете выбрать, в том числе:

  1. Динамическая библиотека Linq
  2. Динамическое создание Expression во время выполнения
  3. ИспользованиеDictionary содержит критерии, которые вам необходимы для каждого свойства
  4. Просто используйте if / else

Я поделюсь более подробной информацией о вышеупомянутых решениях, и вы сможете выбрать любое из них.


Примечание: Если ответ слишком длинный, возможно, самый простой и очевидный ответ - 4-й вариант.


Вариант 1 - Динамическая библиотека Linq

В качестве опции вы можете добавить System.Linq.Dynamic ссылку на ваш проект, затем послеиспользуя пространство имен System.Linq.Dynamic, вы сможете создавать динамические запросы на IEnumerable<T> или IQueryable<T>, передавая критерии как string, например:

var list = db.Products.ToList();
var result = list.Where("Name = @0", "product1").ToList();

Таким образом, вы можете просто использовать столбецИмя свойства данных и значение столбца в запросе динамически.Чтобы узнать больше о динамическом linq, взгляните на следующие ресурсы:

Вариант 2 - Создание лямбдыВыражение во время выполнения

В качестве другого варианта вы можете создать лямбда-выражение во время выполнения и использовать его с методом 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;
}

и затем использовать его следующим образом:

var list = db.Products.ToList();
var result = list.Where(EqualCriteria<Product>("Name", "product1").Compile()).ToList();

Как вы можете видеть, также в этом решении вы можете использовать данные столбцаимя и значение свойства динамически.

Вариант 3. Использование предопределенных критериев в словаре

В качестве другого варианта вы можете создать словарь, содержащий необходимые критерии, а затем использовать их динамически.Например, допустим, вы создали следующий словарь:

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

Опция 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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...