3

I have a DataGridView and I want to show the operator which values are changed by giving those values a different ForeColor. The operator can decide to discard all changes by clicking on a Discard button. In that case I need to let the cell use the inherited styles.

My problem is that once I created a CellStyle to indicate that it is changed I can't undo this so that the cell uses the inherited style.

I did some research. In the article Cell Styles in the Windows Forms DataGridView Control MSDN warns:

Caching the values stored in the cell's Style property is important regardless of whether a particular style value is set. If you temporarily replace a style setting, restoring it to its original "not set" state ensures that the cell will go back to inheriting the style setting from a higher level.

Alas, this doesn't seem to work:

DataGridViewCell cell = ...;

Debug.Assert(!cell.HasStyle);           // cell is not using its own style
var cachedColor = cell.Style.ForeColor; // cache the original color
cell.Style.ForeColor = Color.Red;       // indicate a change
Debug.Assert(cell.HasStyle);            // now cell is using its own style

// restore to the 'not set' state:
cell.Style.ForeColor = cachedColor;
Debug.Assert(!cell.HasStyle);           // exception, not using inherited style
cell.Style = cell.InheritedStyle;       // try other method to restore
Debug.Assert(!cell.HasStyle);           // still exception

So question: How to restore the style setting to its original "not set" state?

Harald Coppoolse
  • 28,834
  • 7
  • 67
  • 116

1 Answers1

4

It appears I had a complete misunderstanding about Cell.Style and Cell.InheritedStyle.

I thought that the inherited style was the style inherited from the row / alternating row / DataGridView, and that the style was the resulting style.

NOT!

The resulting style is DataGridViewCell.InheritedStyle. This style equals the DataGridViewCell.Style, or if this has a null value, it equals the style of DataGridViewRow.InheritedStyle, which in turn equals the value of DataGridViewRow.DefaultStyle, or if this is null, the DataGridView.AlternatingRowsDefaultCellStyle etc.

So to know which style is actually used, get DataGridViewCell.InheritedStyle, to specify a specific style change the properties of DataGridViewCell.Style which is automatically created and filled with the inherited values when you get it.

To discard the DataGridViewCell.Style, just set it to null. After that DataGridViewCell.HasStyle will be false and DataGridViewCell.InheritedStyle will be the style inherited from the Alternating Rows / all Rows.

Example: - a button "Change" will change the Fore Color of the current cell to red and the BackColor of the complete row to AliceBlue - a button "Discard" will restore to the default cell styles

private void buttonChange_Click(object sender, EventArgs e)
{
    DataGridViewCell cell = this.dataGridView1.CurrentCell;
    DataGridViewRow row = cell.OwningRow;

    if (!row.HasDefaultCellStyle)
    {
        row.DefaultCellStyle.BackColor = Color.AliceBlue;
    }

    if (!cell.HasStyle)
    {
        cell.Style.ForeColor = Color.Red;
    }
}

Result: the current cell is shown with Red foreground color, The current row is shown with AliceBlue background color

private void buttonDiscard_Click(object sender, EventArgs e)
{
    DataGridViewCell cell = this.dataGridView1.CurrentCell;
    DataGridViewRow row = cell.OwningRow;

    if (row.HasDefaultCellStyle)
    {
        row.DefaultCellStyle = null;
        Debug.Assert(!row.HasDefaultCellStyle);
    }
    if (cell.HasStyle)
    {
        cell.Style = null;
        Debug.WriteLine(!cell.HasStyle);
    }   
}

Result: the current cell and current row are shown with their original colors

Harald Coppoolse
  • 28,834
  • 7
  • 67
  • 116