【问题标题】:Filter DataGridView by a textbox when its datasource is a List (C#)当 DataGridView 的数据源是 List 时,通过文本框过滤 DataGridView (C#)
【发布时间】:2018-07-30 20:09:31
【问题描述】:

我正在尝试创建一个文本框样式过滤器,它允许我在 dataGridView 表中仅显示 1 行具有选定匹配条件的行。

该表当前通过数据源绑定到一个列表对象。

public static List<NpcDrop> npcDrops = new List<NpcDrop>();
//populate npcDrops
dataGridView3.DataSource = Program.npcDrops;

这是这样设置的,因此我可以编辑 dataGridView 中的值,并且底层 npcDrops 列表会在单元格更改时自行更新。该列表稍后会保存回文件中。

因此,我无法将列表转换为 DataTable 或任何其他对象,因为这会破坏 dataGridView 和列表之间的关系。我曾想过将列表更改为 DataTable,然后将其更改回 List 类型,但似乎不太可能。

我尝试过通过各种方式解决问题:

a) 使用 BindingSource

BindingSource bs = new BindingSource();
bs.DataSource = Program.npcDrops;
bs.Filter = "npcId like '201001'";
dataGridView3.DataSource = bs;

但是似乎没有应用过滤器(主要是因为基于 List 的 BindingSource 不是 IEnumerable

b) 将我的 DataSource 转换为 DataTable,然后使用 RowFilter 功能

private void searchId_TextChanged(object sender, EventArgs e)
{
    (dataGridView3.DataSource as DataTable).DefaultView.RowFilter = 
    string.Format("npcId='{0}'", searchId.Text);
}

然而,这给了我 Object reference not set to an instance of an object. 错误,因为它似乎无法将 dataGridView 转换为 DataTable。

我的想法真的用完了,我想知道是否有人可以提供帮助^^。

【问题讨论】:

  • 你不能只使用 ICollectionView 并内置过滤器吗?
  • 如果我将列表转换为 ICollectionView,对表进行任何更改都不会反映在我的列表中,这会破坏我在两者之间的双向通信。
  • 您是否尝试过使用BindingList
  • 互联网上流传着一个示例,它实际上是 List 数据的 System.Data DataView 的模拟。它允许排序和过滤。我以前在以前的工作中使用过它。我不记得我在哪里找到的。

标签: c# list filter datagridview


【解决方案1】:

我猜你的意思可能是“搜索”而不是“过滤器”。如果您想在用户输入字符后立即“搜索”某些内容,那么在大多数情况下,当用户在文本框中输入单个字符时,searchId_TextChange 事件将触发。在这种情况下,代码似乎正在从单个字符中“过滤”“Id”。除非表格中有一个单元格等于用户输入的值(在此示例中不会出现,因为它是单个字符)……这很可能会使用户处于“空”状态,因为过滤器不会返回任何匹配项。

因此,由于您似乎需要单行,因此在用户输入“确切”完整数字之前,该行不会出现。可能等到用户输入 x 个字符后再应用过滤器可能会有所帮助。或者只是在文本框旁边添加一个“搜索”按钮。我猜这可能对用户更友好。

最后,为了提供帮助,下面是使用List&lt;T&gt;DataTable 作为DataSources 到两个DataGridViews 的两个示例我将假设NpcDrop 属性IDint。在此示例中,IDint。在DataTable 示例中,ID 被定义为string。添加几个文本框,表单可能如下所示。

左边的网格有一个List&lt;NcpDrop&gt; 作为数据源。右侧的网格使用DataTable 作为DataSource。最初fullNPCDropsListgridTable 填充了相同的数据。两个文本框 TextChanged 事件被连接起来以“过滤”网格。

当为List&lt;NcpDrop&gt; 应用“过滤器”时,会创建一个新的List&lt;NcpDrop&gt; filterList 并填充所有匹配的IDs。这个新的List&lt;NcpDrop&gt; 用作网格DataSource

当“过滤器”应用于DataTable 时,会根据初始DataTalbe 创建一个新的DataView filterData,并根据DataView 中的文本将RowFilter 应用于DataView文本框。这个DataView 然后用作网格的`DataSource。

从图片(下图)可以看出,左侧网格将保持“空”,直到用户输入“整数”数字。另一方面,当用户键入更多字符时,右侧的网格将过滤列表项。右侧的网格显示所有类似于“20102”的五 (5) 位数项目。在用户输入第六 (6) 位数字之前,左侧的网格将保持空白。

总之,尚不清楚确切的要求是什么,从用户的角度来看什么是最佳方法。如果用户正在搜索一个数字并且数据是一个数字,我猜你需要做更多的工作,因为如果不使用等于、小于、大于等,此功能将不可用……

List<NpcDrop> fullNPCDropsList;
DataTable gridTable;

public Form1() {
  InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e) {
  fullNPCDropsList = GetData1();
  dgvListData.DataSource = fullNPCDropsList;
  gridTable = GetData2();
  dgvDataTableData.DataSource = gridTable;
}

private List<NpcDrop> GetData1() {
  List<NpcDrop> drop = new List<NpcDrop>();
  int start = 201000;
  for (int i = 0; i < 100; i++) {
    drop.Add(new NpcDrop(++start));
  }
  return drop;
}

private DataTable GetData2() {
  DataTable dt = new DataTable();
  dt.Columns.Add("ID", typeof(string));
  int start = 201000;
  for (int i = 0; i < 100; i++) {
    dt.Rows.Add((++start).ToString());
  }
  return dt;
}

private void txtListSearchBox_TextChanged(object sender, EventArgs e) {
  if (txtListSearchBox.Text == "") {
    dgvListData.DataSource = fullNPCDropsList;
  }
  else {
    if (int.TryParse(txtListSearchBox.Text, out int value)) {
      List<NpcDrop> filterList = fullNPCDropsList.FindAll(x => x.ID.Equals(value));
      dgvListData.DataSource = filterList;
    }
  }
}

private void txtDTSearchBox_TextChanged(object sender, EventArgs e) {
  if (txtDTSearchBox.Text == "") {
    dgvDataTableData.DataSource = gridTable;
  }
  else {
    DataView filterData = new DataView(gridTable);
    filterData.RowFilter = "ID LIKE '%" + txtDTSearchBox.Text + "%'";
    dgvDataTableData.DataSource = filterData;
  }
}

希望这会有所帮助。

【讨论】:

  • 嗨!首先感谢您的回答。我必须使用第一种方法,因为我必须将数据源保留为 List(因为它稍后会保存回文件)。我会看看我是否会设法编辑 FindAll 以允许我输入部分标准而不是完整的数字,但这正是我想要的:)
猜你喜欢
  • 2013-01-31
  • 2012-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多