简体   繁体   中英

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.

在此处输入图片说明

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. 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. 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.

I have tried approaching the problem from various ways:

a) Using 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 .

b) by converting my DataSource to DataTable and then using the RowFilter functionality

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.

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. In this event it appears the code is “filtering” the “Id” from a single character. 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. 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 . In this example ID is an int . In the DataTable example, the ID is defined as a 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. The grid on the right used the DataTable as a DataSource . Initially fullNPCDropsList and gridTable are filled with the same data. The two text boxes TextChanged events are wired-up to “filter” the grid.

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. This new List<NcpDrop> is used as the grids 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. This DataView is then used as a `DataSource to the grid.

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. The grid on the left will remain empty until the user types the sixth (6) digit.

在此处输入图片说明

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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