Reputation: 54871
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
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
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
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
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
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
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