简体   繁体   English

当数据源是列表(C#)时,通过文本框过滤DataGridView

[英]Filter DataGridView by a textbox when its datasource is a List (C#)

I am trying to create a textbox style filter that would allow me to display only 1 row with selected matching criteria in my dataGridView table. 我正在尝试创建一个文本框样式过滤器,该过滤器仅允许我在dataGridView表中显示具有选定匹配条件的1行。

在此处输入图片说明

The table is currently bound to a list object via datasource. 该表当前通过数据源绑定到列表对象。

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

This is set this way so I can edit the value in the dataGridView and the underlying npcDrops list would update itself on cell change. 以此方式进行设置,以便我可以在dataGridView中编辑值,并且基础npcDrops列表将在单元格更改时自动更新。 The list is later saved back to the file. 列表稍后保存回到文件中。

Because of that I cannot convert the list to a DataTable or any other object as this would break the relationship between the dataGridView and the list. 因此,我无法将列表转换为DataTable或任何其他对象,因为这会破坏dataGridView与列表之间的关系。 I have thought about changing the list to DataTable and then changing it back to the List type but it seems quite impossible to do. 我曾考虑过将列表更改为DataTable,然后再将其更改回List类型,但这似乎是不可能的。

I have tried approaching the problem from various ways: 我尝试通过多种方式解决该问题:

a) Using BindingSource a)使用BindingSource

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

However the Filter does not seem to be applied (mostly due to fact that the BindingSource based on a List is not IEnumerable . 但是,似乎未应用筛选器(主要是由于基于List的BindingSource不是IEnumerable的事实。

b) by converting my DataSource to DataTable and then using the RowFilter functionality b)通过将我的数据源转换为数据表,然后使用RowFilter功能

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

this however gave me Object reference not set to an instance of an object. 然而,这给了我对象引用未设置为对象的实例。 error instead as it seems that it is unable to cast the dataGridView to DataTable. 错误,似乎无法将dataGridView强制转换为DataTable。

I have really ran out of the ideas and I am wondering if anyone could help ^^. 我的想法真的用光了,我想知道是否有人可以帮助^^。

I am guessing you may be meaning a “search” instead of a “filter”. 我猜您可能是在说“搜索”而不是“过滤器”。 If you want to “search” for something as soon as the user types a character, then in most cases, when the user types a single character into the text box, the searchId_TextChange event will fire. 如果您想在用户键入字符后立即“搜索”某些内容,则在大多数情况下,当用户在文本框中键入单个字符时,将触发searchId_TextChange事件。 In this event it appears the code is “filtering” the “Id” from a single character. 在这种情况下,似乎代码正在从单个字符“过滤”“ Id”。 Unless there is a cell in the table that equals the value the user typed in (which there will not be in this example since it is a single character) … this will most likely leave the grid in an “empty” state to the user because the filter is not going to return any matches. 除非表中有一个单元格等于用户键入的值(在本示例中因为单个字符而没有),否则这很可能使用户处于“空”状态,因为过滤器将不返回任何匹配项。

Therefore, since it appears you want a single row, then that row will not appear until the user types in the “exact” full number. 因此,由于您只想显示一行,所以直到用户键入“完全”完整的数字后,该行才会出现。 It may be beneficial to possibly wait until the user has typed in x number of characters before you apply the filter. 在应用过滤器之前,可能要等到用户键入了x个字符后,这才是有益的。 Or simply add a “search” button next to the text box. 或者只是在文本框旁边添加一个“搜索”按钮。 I am guessing this may be more user friendly. 我猜这可能对用户更友好。

Lastly, to help, below are two examples of using a List<T> and a DataTable as DataSources to two DataGridViews I will assume the NpcDrop property ID is an int . 最后,为了提供帮助,下面是两个使用List<T>DataTable作为两个DataGridViewsDataTable DataSources示例,我将假设NpcDrop属性IDint In this example ID is an int . 在此示例中, ID是一个int In the DataTable example, the ID is defined as a string . DataTable示例中, ID被定义为string Add a couple of text boxes and the form may look something like below. 添加几个文本框,该窗体可能如下所示。

在此处输入图片说明

The grid on the left has a List<NcpDrop> as a data source. 左侧的网格具有List<NcpDrop>作为数据源。 The grid on the right used the DataTable as a DataSource . 右侧的网格使用DataTable作为DataSource Initially fullNPCDropsList and gridTable are filled with the same data. 最初, fullNPCDropsListgridTable用相同的数据填充。 The two text boxes TextChanged events are wired-up to “filter” the grid. 连接两个文本框TextChanged事件以“过滤”网格。

When a “filter” is applied for the List<NcpDrop> , a new List<NcpDrop> filterList is created and filled with all the ID s that match. 当对List<NcpDrop>应用“过滤器”时,将创建一个新的List<NcpDrop> filterList ,并用所有匹配的ID填充。 This new List<NcpDrop> is used as the grids DataSource . 此新的List<NcpDrop>用作网格DataSource

When a “filter” is applied to the DataTable a new DataView filterData is created from the initial DataTalbe and a RowFilter is applied to the DataView based on what text is in the text box. 将“过滤器”应用于DataTable将从初始DataTalbe创建一个新的DataView filterData并根据文本框中的文本将RowFilter应用于DataView This DataView is then used as a `DataSource to the grid. 然后将此DataView用作网格的DataSource。

As can be seen from the picture (below) that the left grid will remain “empty” until the user types in the “whole” number. 从图片(下图)可以看出,左网格将保持“空”,直到用户键入“整数”。 The grid on the right on the other hand will filter the list items when the user types more characters. 另一方面,当用户键入更多字符时,右侧的网格将过滤列表项。 The grid on the right displays all the items that are like “20102” with five (5) digits. 右侧的网格显示所有带有五(5)位数字的“ 20102”项目。 The grid on the left will remain empty until the user types the sixth (6) digit. 在用户键入第六(6)位数字之前,左侧的网格将保持空白。

在此处输入图片说明

In conclusion, it is not clear what the exact requirements are and what would be the best approach from a user perspective. 总之,从用户的角度来看,确切的要求是什么以及什么是最佳方法尚不清楚。 If a user is searching for a number and the data is a number, I am guessing you will need to do more work as this functionality is not available without using equal, less than, greater than etc… 如果用户正在搜索一个数字而数据是一个数字,我想您将需要做更多的工作,因为如果不使用均等,小于,大于等功能,此功能将不可用。

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

Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM