Omer Waheed Omer Waheed - 29 days ago 7
C# Question

Custom Search in DataGridView

I am creating a program where I need to search in every column of grid but that search-textbox should be applied into a cell of DataGridView. What I mean here is
a DataGridView with top most row as a search row which will apply search in data below it.

Like the example below:

enter image description here

This DataGridView has search cell in the first row which apply search to its values below it.

TaW TaW
Answer

This can be done, and as you can see below it isn't really a lot of code you need. But you do need to use a few tricks, so here is an example you may want to study:

enter image description here

It assumes you have a DataGridView bound to a DataTable with AllowUserToAddRows set to false.

The first thing you want is grab the editing control, usually a TextBox when the user starts editing:

 DataGridViewTextBoxEditingControl editDgvEc = null;  // at class level!

We grab it in this event:

private void dataGridView1_EditingControlShowing(object sender,
                           DataGridViewEditingControlShowingEventArgs e)
{
    // unhook the old handle
    if (editDgvEc != null) editDgvEc.TextChanged -= editDgvEc_TextChanged;
    // store a reference
    editDgvEc = e.Control as DataGridViewTextBoxEditingControl;
    // hook up the TextChanged event
    editDgvEc.TextChanged += editDgvEc_TextChanged;
}

In the TextChanged event we do a few tests and then select all fitting rows:

void editDgvEc_TextChanged(object sender, EventArgs e)
{
    if (dataGridView1.CurrentCell.RowIndex == 0)
    {
        int col = dataGridView1.CurrentCell.ColumnIndex;
        if (editDgvEc.Text == "") dataGridView1.ClearSelection();
        else
            foreach (DataGridViewRow row in dataGridView1.Rows)
            {
                if (row.Index > 0)  row.Selected = 
                    row.Cells[col].Value.ToString().Contains(editDgvEc.Text);
            }
    }
}

So you can see the selection process at work while you type. If there are a lot of rows, you may want to change that, maybe by grabbing the search text not from the editing textbox but from the cell itself in the CellEndEdit event..

Finally we want to set up the search row. We need to do that after the DataTable dt is filled:

dataGridView1.DataSource = dt;
DataRow dr = dt.NewRow();
dt.Rows.InsertAt(dr, 0);
dataGridView1.Rows[0].Frozen = true;
dataGridView1.Rows[0].DividerHeight = 2;
dataGridView1.Rows[0].DefaultCellStyle.BackColor = Color.LightBlue;

For an even nicer touch we can code the CellPainting event to draw a custom RowHeader :

private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    if (e.ColumnIndex >= 0 || e.RowIndex != 0) return;
    e.Graphics.DrawString("$", new Font("Wingdings",11f), Brushes.Black, e.CellBounds);
    e.Handled = true;
}

If your DGV is not databound the code can simply be adapted by adding the search row directly to the DGV instead of adding it to the data source.

Comments