Search code examples
c#winformsdatagridviewdatagridviewcolumn

DataGridViewCell PaintErrorIcon method


I'm trying to overwrite the errorIcon of a certain column in a DataGridView. I've found some information about this online but the PaintErrorIcon method from my custom class never gets called. To test I added an override for the normal Paint and using the test code below I do get "PAINT" in my output, but when I set an errorText to the cells, I don't see "ERROR PAINT" (the cells DO get an error icon and Paint gets called when the error text is set).

public class DataGridViewWarningCell: DataGridViewTextBoxCell
{
    protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
    {
        base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
        Console.WriteLine("PAINT");
    }

    protected override void PaintErrorIcon(Graphics graphics, Rectangle clipBounds, Rectangle cellValueBounds, string errorText)
    {
        base.PaintErrorIcon(graphics, clipBounds, cellValueBounds, errorText);
        Console.WriteLine("ERROR PAINT");
    }
}

I've added the column to my DataGridView like this:

public class DataGridViewWarningColumn : DataGridViewColumn
{
    public DataGridViewWarningColumn()
    {
        this.CellTemplate = new DataGridViewWarningCell();
    }
}

Then in my form code:

var warningColumn = new DataGridViewWarningColumn();
fileGrid.Columns.Add(warningColumn);

Solution

  • Hm, seems like this won't work without a little nudging..

    Here is what I tried, but you will want to change the real graphics stuff, obviously..

    protected override void Paint(Graphics graphics, Rectangle clipBounds, 
              Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, 
              object value, object formattedValue, string errorText,
              DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle 
              advancedBorderStyle, DataGridViewPaintParts paintParts)
    {
        base.Paint( graphics, clipBounds, cellBounds, rowIndex, cellState, value, 
                    formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
         Console.WriteLine("PAINT");
         // call it by hand:
         if (errorText != "")  PaintErrorIcon(graphics, clipBounds, cellBounds, errorText);
    }
    
    protected override void PaintErrorIcon(Graphics graphics, 
                            Rectangle clipBounds, Rectangle cellValueBounds, string errorText)
    {
        // not the std icon, please
        //base.PaintErrorIcon(graphics, clipBounds, cellValueBounds, errorText);
        Console.WriteLine("ERROR PAINT");
        // aah, that's better ;-)
        graphics.FillRectangle(Brushes.Fuchsia, new Rectangle( clipBounds.Right - 10,   
                 cellValueBounds.Y + 3, clipBounds.Right, cellValueBounds.Height - 6));
     }
    

    I have turned off ShowCellErrors and commented out the call to the base method.

    If you can't turn off ShowCellErrors for the DGV you will have to take care to overpaint the standard icon completely, as it still gets drawn, even though we don't call base.PaintErrorIcon. Surely another symptom of something going not as expected..

    I'm not sure about the best Bounds Rectangle to hand in, but it seems to do something, so that's a start..