2

This is the case: I want to search for a word in a whole DataGridView through looping it's Rows, and then for each match I highlight the word. The major inflexibility I face is that columns have different System.Windows.Forms.DataGridViewContentAlignments. So in paiting (highlighting) mathced word in cells I should take care of cell's ContentAlignment.

So far I have written the following code to find the matches

private int FindAllMatches()
{
    int itemsFound = 0;
    for (int r = 0; r < dgvMain.Rows.Count; r++)
    {
        DataGridViewRow row = dgvMain.Rows[r];
        for (int c = 0; c < Columns.Count; c++)
        {
            string cellValue = (dgvMain.Rows[r].Cells[c].Value ?? "").ToString();
            if (cellValue.Contains(SearchValue.ToString()))
            {
                HighlightRow(row); // highlights whole row, weak solution
                itemsFound++;
                break;
            }
        }
    }
    return itemsFound;
}

But as you see I have currently managed to highlight the rows which have at least one match. What I need is a code to highlight only the portion of cell which matches my specific word (SearchValue).

I know I should use the CellPainting Event, but I don't know how to paint the word inside a Cell considering the Cell's ContentAlignment

Mahdi Tahsildari
  • 13,065
  • 14
  • 55
  • 94
  • I have answered [similar question](http://stackoverflow.com/questions/21989469/set-two-colors-text-in-a-single-datagridview-cell/21997432#21997432) – Junaith Mar 11 '14 at 10:46
  • Hi @Junaith, in the last couple of weeks I have been asking about `DataGridView` and you have been answering them :) I think we should start a business together ;) kidding. I'll check it and let you know in a couple of minutes ... – Mahdi Tahsildari Mar 11 '14 at 10:49
  • I've got a problem @Junaith, your code is fine for English text, but my language is Persian that is written in `RightToLeft` direction. With the [Current Answer you have provided](http://stackoverflow.com/questions/21989469/set-two-colors-text-in-a-single-datagridview-cell/21997432#21997432) my text is shown wrong, for example if my cell text is 'نصب قفل سخت افزاری' it is shown like 'فزاری نصب قفل سخت ا' – Mahdi Tahsildari Mar 11 '14 at 11:00

1 Answers1

1

I have modified the my answer to this question to consider the direction and content alignment. It works for default alignment but you have to improve the code for other alignments.

void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    if (e.RowIndex != -1 && e.Value != null && e.Value.ToString().Length > 5 && e.ColumnIndex == 2)
    {
        if (!e.Handled)
        {
            e.Handled = true;
            e.PaintBackground(e.CellBounds, dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Selected);
        }
        if ((e.PaintParts & DataGridViewPaintParts.ContentForeground) != DataGridViewPaintParts.None)
        {
            bool rightToLeft = this.RightToLeft == RightToLeft.Yes ? true:false;
            string text = e.Value.ToString();
            string textPart1 = text.Substring(0, text.Length - 5);
            string textPart2 = text.Substring(text.Length - 5, 5);
            Size fullsize = TextRenderer.MeasureText(text, e.CellStyle.Font);
            Size size1 = TextRenderer.MeasureText(textPart1, e.CellStyle.Font);
            Size size2 = TextRenderer.MeasureText(textPart2, e.CellStyle.Font);
            Rectangle rect1 = new Rectangle(e.CellBounds.Location, e.CellBounds.Size);
            TextFormatFlags flags = GetFlagsForCellStyleAlignment(rightToLeft, e.CellStyle.Alignment);
            TextRenderer.DrawText(e.Graphics, text, e.CellStyle.Font, rect1, Color.Crimson, flags);
            using (Brush cellForeBrush = new SolidBrush(e.CellStyle.ForeColor))
            {
                TextRenderer.DrawText(e.Graphics, textPart1, e.CellStyle.Font, rect1, e.CellStyle.ForeColor, flags);
            }
        }
    }
}

TextFormatFlags GetFlagsForCellStyleAlignment(bool rigthToLeft, DataGridViewContentAlignment alignment)
{
    TextFormatFlags flags = TextFormatFlags.Default;
    switch (alignment)
    {
        case DataGridViewContentAlignment.TopLeft:
            {
                flags = TextFormatFlags.Default;
                if (rigthToLeft)
                {
                    flags |= TextFormatFlags.Right;
                }
                break;
            }
        case DataGridViewContentAlignment.MiddleLeft:
            {
                flags = TextFormatFlags.VerticalCenter;
                if (rigthToLeft)
                {
                    flags |= TextFormatFlags.Right;
                }
                break;
            }
    }
    if (rigthToLeft)
        flags |= TextFormatFlags.RightToLeft;
    return flags;
}
Community
  • 1
  • 1
Junaith
  • 3,298
  • 24
  • 34
  • Good code for a start, but not complete. Your code acts differently when the cell `StartsWith` a word and when it `Contains` the word in it and does not start with it. – Mahdi Tahsildari Mar 11 '14 at 14:52
  • By the way, I have changed your code. So it's not your fault. Code should be worked on... – Mahdi Tahsildari Mar 11 '14 at 14:54
  • Yeah I know... but it will be challenging as you have to change the text alignment based on where your colored letters are in the word. – Junaith Mar 11 '14 at 14:54
  • I'm working on it, but it would be great if you could give me a more complete sample, not because I want it to be easier, because I don't understand some parts and get confused. – Mahdi Tahsildari Mar 11 '14 at 14:56
  • Ok I will try... Do you want to highlight full word or one word in a sentence like Hello **World** or multiple words in a sentence like Hello **World**, Nice to **meet** you or letters in a word like **pass**ive. – Junaith Mar 11 '14 at 15:14
  • Thanks a lot, actually I want to highlight a word but if it occurs multiple times in a cell all of them should get highlighted. For example: **If** my code is d**if**erent from your code, any **if** in it should be counted sign**if**icantly. – Mahdi Tahsildari Mar 11 '14 at 18:54
  • Then I would suggest you to have a custom DataGridViewRitchTextBoxColumn...you can achieve your highlighting easily... I am remember answering a question with link to an article for RichTextColumn...you can search it – Junaith Mar 11 '14 at 18:58
  • I think you mean [Access RitchTextBox Control ...](http://stackoverflow.com/a/20973851/1471381) answer, but I'm doing this for search and not in edit mode. – Mahdi Tahsildari Mar 11 '14 at 19:23
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/49547/discussion-between-mahdi-tahsildari-and-junaith) – Mahdi Tahsildari Mar 12 '14 at 09:50