Matt Frear
Matt Frear

Reputation: 54871

DataGridViewImageColumn red x

I've created a DataGridView and added a DataGridViewImageColumn (using the Designer).

The DataGridView has "AllowUserToAddRows = true" so a blank row is displayed for the user to enter a new row in. In this blank row the DataGridViewImageColumn displays a red x. I want to always display the same image in the column regardless of whether the row has any data or not (I am binding the cell's click event so using the DataGridViewImageColumn as a button).

How do I get rid of the red x?

Upvotes: 5

Views: 9606

Answers (6)

Ulf Kristiansen
Ulf Kristiansen

Reputation: 1631

The MSDN documentation is rather verbose on this:

By default, empty cells display a default error graphic. To prevent this graphic from appearing for cell values equal to null or DBNull.Value, set the DataGridViewCellStyle.NullValue property of the cell style object returned by the DefaultCellStyle property to null before adding rows to the control. This does not affect the row for new records, however. To prevent the error graphic from appearing in the row for new records when the control AllowUserToAddRows property value is true, you must also either explicitly set the cell value to null in a handler for the control RowsAdded event or set the column CellTemplate property to an instance of a DataGridViewImageCell-derived type with an overridden DefaultNewRowValue property that returns null.

Translated to code it means you can do this before adding any rows:

var column = new DataGridViewImageColumn();
column.DefaultCellStyle.NullValue = null;
column.CellTemplate = new DataGridViewEmptyImageCell();

And then put this class somewhere:

private class DataGridViewEmptyImageCell : DataGridViewImageCell
{
    public override object DefaultNewRowValue { get { return null; } }
}

Or set Cell.Value to null in the Rows.Added event.

Upvotes: 1

Luan
Luan

Reputation: 166

Another way to avoid this default behavior for all the DataGridViewImageColumn elements in a DataGridView is to intercept the CellFormatting event:

dataGridView1.CellFormatting += delegate(object sender, DataGridViewCellFormattingEventArgs e)
{
    if (e.RowIndex < 0 || e.ColumnIndex < 0)
        return;

    var grid = (DataGridView)sender;
    if (grid.Columns[e.ColumnIndex] is DataGridViewImageColumn &&
        grid[e.ColumnIndex, e.RowIndex].DefaultNewRowValue.Equals(e.Value))
        e.Value = null;
};

This way the component will always use the NullValue image for the cell instead of the default "unavailable image".

Upvotes: 0

Michael O&#39;Leary
Michael O&#39;Leary

Reputation: 21

I looked through these solutions and the way I got this to work was to do this after InitializeComponent() call in the constructor to make the default image for data bound rows an empty image

dataGridView1.Columns[0].DefaultCellStyle.NullValue = null;

And hook the RowPrePaintEvent to remove the red X for the empty row at the end of the grid because AllowUserToAddRows = true:

private void dataGridView1_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
{
      if (e.RowIndex >= numberOfRows)
      {
           dataGridView1.Rows[e.RowIndex].Cells[0].Value = null;
      }
}

Where numberOfRows is the number of valid rows in the grid. Just spent a few hours dealing with this. Hope this saves someone else the headache...

Upvotes: 2

younus
younus

Reputation: 21

I used IsNewRow property of grid.row like this

private void dgUserFileList_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e) {
      DataGridViewRow row = dgUserFileList.Rows[e.RowIndex];
      if (row.IsNewRow) {
          row.Cells[0].Value = null;
        }
      }
    }

Upvotes: 2

Chris Doggett
Chris Doggett

Reputation: 20757

I use an ImageList to hold all my images, but here's a trimmed down version that should help. You're right to set the Value, but you should set it to the null-equivalent of a bitmap, which is just a static blank image. I use:

e.Value = (imageIndex != int.MinValue) ? imageList.Images[imageIndex] : nullImage;

where nullImage is defined earlier in the class as:

private readonly Image nullImage = new Bitmap(1, 1);

Upvotes: 4

Matt Frear
Matt Frear

Reputation: 54871

I've found a solution, but I'm not sure it's the best way.

I override the RowsAdded event and set the Value of the DataGridViewImageColumn to null. I think since the value is null, it displays the image.

private void dgvWorksheet_RowsAdded(object sender, 
     DataGridViewRowsAddedEventArgs e)
{
    dgvWorksheet.Rows[e.RowIndex].Cells[colStartClock.Index].Value = null;
}

I also set the NullValue of the Column to null in the Form_Load

colStartClock.DefaultCellStyle.NullValue = null;

I'm not sure if there's anything else I need to do. It seems to be working but it seems a bit buggy - random clicking sometimes results in exceptions, so more investigation is needed.

Upvotes: 1

Related Questions