0

I have gridview with five columns. i have loaded the data on it. the user can edit the text within the column cell. if the user edited the text,those edited text must be red. Only edited

e.g

stackoverflow = StackOverFlow (you will note that i have change/edited to caps. those edited caps must change color. in this case S O and F will change color to red)

this is what i have tried but not working the way

 private void Gridview_CellBeginEdit_1(object sender, DataGridViewCellCancelEventArgs e)
    {
        DataGridViewCell cell = Gridview_Output[e.ColumnIndex, e.RowIndex];
        if (cell.Tag != null && cell.Tag.ToString() != cell.Value.ToString())
            cell.Style.ForeColor = Color.Red;
        else
            DataGridViewCell cell = Gridview_Output[e.ColumnIndex, e.RowIndex];
            cell.Tag = cell.Value != null ? cell.Value : "";

    }
TaW
  • 53,122
  • 8
  • 69
  • 111
prosts
  • 141
  • 2
  • 2
  • 10
  • If you want only the chars which have changed to be a different color, than you will need to paint the cell yourself to accomplish that. The cell's style's ForeColor will affect all the contents of the cell. Look into the [CellPainting](https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.cellpainting%28v=vs.110%29.aspx) event. – Anthony Mar 30 '15 at 14:29
  • Unless you handle the drawing yourself I don't think `DataGridViewCell` will support what you want. I don't know many built-in controls that will support what you want to be honest. RichTextBox will support it, which you may be able to add to a cell (I have never tried it), but that might not be a good idea anyway, they can be painful if not used correctly – musefan Mar 30 '15 at 14:29
  • This will be a painful task, I'm sure. perhaps this link may help you http://stackoverflow.com/questions/3448017/highlight-part-of-a-text-in-a-cell-of-datagridview/21073218#21073218 – Zohar Peled Mar 30 '15 at 14:34
  • You might find [this to be of some use](http://stackoverflow.com/questions/21989469/set-two-colors-text-in-a-single-datagridview-cell) – musefan Mar 30 '15 at 14:34
  • One option that might require less complicated work is to display the before and after values somewhere other than in the cell. For example, you could colour the text in the cell red (changing the text colour in a cell is easy) if it has been edited and then have a tool-tip that appears when you mouse over the cell, showing both the before and after values. This could actually be more helpful, since the method you suggest would not be that useful if someone changed 'stackoverflow' to 'google' - all you would see was 'google' in red, but no indication of the original value. – Ulric Mar 30 '15 at 14:45
  • 1
    This will require you to keep track of those changes. What about multiple edits? If you have them ready you can do a series of DrawStrings using two Pens; not terribly hard but details depend on the Cell layout..Note that the changes are the __real__ challenge and that your example looks deceptively simple. This problem is anything but simple!! Google 'text diff" to get a glimpse of the size of the actual problem. – TaW Mar 30 '15 at 15:10
  • To make my point clearer: The changed characters are trivial but what about characters that are inserted or deleted??? How will you get back to synch with the original text??? If you don't then after a deletion/insertion the complete rest could be seen as changed.. – TaW Mar 30 '15 at 15:14
  • I will reset the color on Save button... am trying to follow this example but the challenge is that i want it on the grid. e.g. from this code diffStrings.Add(new Tuple(c1, "1234")) How can i put gridview rows. e.g row 1,2,3,4,5,6 so that it will fires when theres changes? – prosts Apr 01 '15 at 12:25

1 Answers1

2

Here is a code example for the easy part:

enter image description here

It checks for one column (0) in one row (4) and then draws the strings prepared in a list of tuples. You can change the data structure easily..

List<Tuple<SolidBrush, string>> diffStrings = new List<Tuple<SolidBrush, string>>();

private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    if (e.RowIndex != 4 || e.ColumnIndex != 0) { return; }  // only one test-cell
    float x = e.CellBounds.Left + 1;
    float y = e.CellBounds.Top + 1;

    e.PaintBackground(e.CellBounds,true);
    foreach (Tuple<SolidBrush, string> kv in diffStrings)
    {
        SizeF size = e.Graphics.MeasureString(kv.Item2, Font, 
                     e.CellBounds.Size, StringFormat.GenericTypographic);
        if (x + size.Width > e.CellBounds.Left + e.CellBounds.Width)  
           {x = e.CellBounds.Left + 1; y += size.Height; }
        e.Graphics.DrawString(kv.Item2, Font, kv.Item1,   x , y);
        x += size.Width;

    }
    e.Handled = true;
}

But where will you get the data from??

Here is how I created the test data, which are only meant to show the drawing in different colors:

SolidBrush c1 = new SolidBrush(Color.Black);
SolidBrush c2 = new SolidBrush(Color.Red);

diffStrings.Add(new Tuple<SolidBrush, string>(c1, "1234"));
diffStrings.Add(new Tuple<SolidBrush, string>(c2, "M"));
diffStrings.Add(new Tuple<SolidBrush, string>(c1, "1234"));
diffStrings.Add(new Tuple<SolidBrush, string>(c2, "ÖÄÜ"));
diffStrings.Add(new Tuple<SolidBrush, string>(c1, "1234"));
diffStrings.Add(new Tuple<SolidBrush, string>(c2, "ÖÄÜ"));
diffStrings.Add(new Tuple<SolidBrush, string>(c1, "1234"));
..

You will need to solve the problem of writing a Diff function that can fill the structure. It would help if you know restraints, like maybe that the length can't change..

You can use the Cells' Values and diff them with their old values if you store these in the Cells' Tags. You would have to handle e.g. the CellBeginEdit and/or CellEndEdit event to manage the storage of the two values but the real challenge is to get the diffs, especially when there are inserted or deleted characters!

The example above aligns the text TopLeft. Including all DataGridViewContentAlignment options would complicate the code somewhat, but only in a limited way. The same goes for splitting after word boundaries or managing embeded line feeds.. - Writing a Diff function however is really tough. See here for an example of how to use a ready-made one..!

Community
  • 1
  • 1
TaW
  • 53,122
  • 8
  • 69
  • 111
  • Nice job. Unfortunately I can give only +1 – γηράσκω δ' αεί πολλά διδασκόμε Mar 30 '15 at 23:42
  • 1
    @γηράσκω: Thank you. Including `DataGridViewContentAlignment` would complicate the code somewhat, but only in a limited way. Writing a __Diff__ is tough. See [here for an example..](http://stackoverflow.com/questions/24887238/how-to-compare-two-rich-text-box-contents-and-highlight-the-characters-that-are/24970638?s=1|0.2729#24970638)! – TaW Mar 31 '15 at 00:54