DaniKR
DaniKR

Reputation: 2448

How to highlight search text in DataGridView in specific column?

Reference to this question Highlight search in datagridview, solution works, but it higlight search string in whole datagridview.

My Question is, is it possible to higlight search text in specific column?

Here is copy of code from solution:

string keyValue = "Co"; //search text

private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    if (e.Value == null) return;

    StringFormat sf = StringFormat.GenericTypographic;
    sf.FormatFlags = sf.FormatFlags | StringFormatFlags.MeasureTrailingSpaces | StringFormatFlags.DisplayFormatControl;
    e.PaintBackground(e.CellBounds, true);

    SolidBrush br = new SolidBrush(Color.White);
    if (((int)e.State & (int)DataGridViewElementStates.Selected) == 0)
        br.Color = Color.Black;

    string text = e.Value.ToString();
    SizeF textSize = e.Graphics.MeasureString(text, Font, e.CellBounds.Width, sf);

    int keyPos = text.IndexOf(keyValue, StringComparison.OrdinalIgnoreCase);
    if (keyPos >= 0)
    {
        SizeF textMetricSize = new SizeF(0, 0);
        if (keyPos >= 1)
        {
            string textMetric = text.Substring(0, keyPos);
            textMetricSize = e.Graphics.MeasureString(textMetric, Font, e.CellBounds.Width, sf);
        }

        SizeF keySize = e.Graphics.MeasureString(text.Substring(keyPos, keyValue.Length), Font, e.CellBounds.Width, sf);
        float left = e.CellBounds.Left + (keyPos <= 0 ? 0 : textMetricSize.Width) + 2;
        RectangleF keyRect = new RectangleF(left, e.CellBounds.Top + 1, keySize.Width, e.CellBounds.Height - 2);

        var fillBrush = new SolidBrush(Color.Yellow);
        e.Graphics.FillRectangle(fillBrush, keyRect);
        fillBrush.Dispose();
    }
    e.Graphics.DrawString(text, Font, br, new PointF(e.CellBounds.Left + 2, e.CellBounds.Top + (e.CellBounds.Height - textSize.Height) / 2), sf);
    e.Handled = true;

    br.Dispose();
}

Upvotes: 1

Views: 587

Answers (1)

TaW
TaW

Reputation: 54433

Usually, when owner-drawing a Control the Paint event is used for the whole area.

The DataGridView.CellPainting event is different; it is called for every (visible) Cell in the DGV separately.

This means that you can completely dimiss it for some Cells, Rows or Columns simply by checking which Cell it is about to paint.

The DataGridViewCellPaintingEventArgs include e.ColumnIndex and e.RowIndex. You can solve your problem by testing for a certain column name like this:

if (dataGridView1.Columns[e.ColumnIndex].Name != "name") return;

You could also test for a list of columns to include or exclude:

var names = new List<string> {"firstname", "lastname"};
string colName = dataGridView1.Columns[e.ColumnIndex].Name;
if (names.Contains(colName)) return;

Or hack it like this:

string names = " firstname lastname ";
string colName = dataGridView1.Columns[e.ColumnIndex].Name;
if (names.Contains(" " + colName + " ")) return;

Rows don't have Names, so you need to check for their indices. Note that the rows headers column as well as the column headers row have -1 as their index and can be both painted and skipped like other cells.

Other noteworthy details on paint a DGV can be found on MSDN on DataGridViewCellPaintingEventArgs , PaintParts, RowPrePaint , RowPostPaint ..

Upvotes: 1

Related Questions