如何重构此代码以搜索 BindingList 的多个属性?

How to refactor this code to search through multiple properties of a BindingList?

我在 Windows 表单中创建了一个搜索按钮和一个关联的文本框,以通过 DataGridView 进行搜索。 DGV 在 BindingList 中显示信息。 BindingList 具有 PartID、Name、Price、Instock、Min 和 Max 属性,它们是 int、string、decimal、int、int 和 int 类型。我可以让搜索正常运行,但代码本身看起来很笨重。如何使用更少的代码在 BindingList 中进行 'for' 循环搜索?

for (int i = 0; i < Inventory.AllParts.Count; i++)
{
    //I would like to condense this if statement into one line of code
    if (Inventory.AllParts[i].PartID.ToString().Contains(partsSearchTextBox.Text.ToString())
        || Inventory.AllParts[i].Name.ToString().Contains(partsSearchTextBox.Text.ToString())
        || Inventory.AllParts[i].Price.ToString().Contains(partsSearchTextBox.Text.ToString())
        || Inventory.AllParts[i].Instock.ToString().Contains(partsSearchTextBox.Text.ToString())
        || Inventory.AllParts[i].Min.ToString().Contains(partsSearchTextBox.Text.ToString())
        || Inventory.AllParts[i].Max.ToString().Contains(partsSearchTextBox.Text.ToString()))
    {
        dgvParts.Rows[i].Selected = true;
        found = true;
    }
}

例如,您可以这样重构:

bool CheckOR(Func<string, bool> predicate, params object[] values)
{
  //if ( predicate == null ) return false;
  foreach ( object value in values )
    if ( predicate(value.ToString()) )
      return true;
  return false;
}

for ( int i = 0; i < Inventory.AllParts.Count; i++ )
{
  if ( CheckOR(s => s.Contains(partsSearchTextBox.Text)
               Inventory.AllParts[i].PartID,
               Inventory.AllParts[i].Name,
               Inventory.AllParts[i].Price,
               Inventory.AllParts[i].Instock,
               Inventory.AllParts[i].Min,
               Inventory.AllParts[i].Max) )
  {
    dgvParts.Rows[i].Selected = true;
    found = true;
  }
}

使用 Linq:

bool CheckOR(Func<string, bool> predicate, params object[] values)
{
  return values.Any(v => predicate(v.ToString()));
}

简化为:

for ( int i = 0; i < Inventory.AllParts.Count; i++ )
{
  var values = new object[]
  {
    Inventory.AllParts[i].PartID,
    Inventory.AllParts[i].Name,
    Inventory.AllParts[i].Price,
    Inventory.AllParts[i].Instock,
    Inventory.AllParts[i].Min,
    Inventory.AllParts[i].Max
  };
  if ( values.Any(v => v.ToString().Contains(partsSearchTextBox.Text)) )
  {
    dgvParts.Rows[i].Selected = true;
    found = true;
  }
}

需要更多细节以进一步改进,以防万一,也许可以使用反射,因为如果检查所有字段,我们就可以解析属性。或者可以使用带有属性名称的预定义数组。

您也可以使用这个 BindingListView 的过滤器,效果很好。

BindingSource.Filter,但在标准BindingList上不起作用。

相关问题

Applying a filter to a BindingSource, but it doesn't work

DataGridView Filter a BindingSource with a List of object as DataSource

Filtering BindingList

C# filter objects with BindingSource in DataGridView