Reputation: 5068
I need to change the back color of a DataGridView
cell based on certain conditions, as the user is editing the cell. Right now I can only change the BackColor
after the cell loses focus.
Specifically, while the user is typing in a cell, I need to check the DataTable
that the DataGridView
is bound to to compare what the user is typing to what value is in the DataTable in the corresponding cell. If it's different, I need to change the BackColor
to Yellow. And if the user changes the value in the cell back to the original value in the DataTable, I need to remove the color.
I tried messing around with the KeyPress
event, but I can't figure out how to get the specific row/column index of the cell being edited so I can correctly check it's value against the corresponding DataTable
's row/column index value.
Upvotes: 2
Views: 1133
Reputation: 125197
It's not easy, You need to handle a few things:
TextChanged
event and in the TextChanged
event handler, compare the text with the datasource value and colorize textbox based on that.Here is the screen capture:
Here is a working example:
public DataTable GetProducts()
{
var products = new DataTable();
products.Columns.Add("Id", typeof(int));
products.Columns.Add("Name", typeof(string));
products.Columns.Add("Price", typeof(int));
products.Rows.Add(1, "Product 1", 100);
products.Rows.Add(2, "Product 2", 200);
products.AcceptChanges();
return products;
}
private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.AutoGenerateColumns = true;
dataGridView1.DataSource = GetProducts();
dataGridView1.EditMode = DataGridViewEditMode.EditOnEnter;
dataGridView1.EditingControlShowing += dataGridView1_EditingControlShowing;
dataGridView1.CellPainting += dataGridView1_CellPainting;
dataGridView1.CellBeginEdit += dataGridView1_CellBeginEdit;
dataGridView1.CellEndEdit += dataGridView1_CellEndEdit;
}
private void dataGridView1_CellEndEdit(object sender,
DataGridViewCellEventArgs e)
{
if (e.ColumnIndex < 0 || e.RowIndex < 0 || e.RowIndex == dataGridView1.NewRowIndex)
return;
var drv = dataGridView1.Rows[e.RowIndex].DataBoundItem as DataRowView;
if (drv != null)
{
drv.EndEdit();
}
}
private void dataGridView1_CellBeginEdit(object sender,
DataGridViewCellCancelEventArgs e)
{
if (e.ColumnIndex < 0 || e.RowIndex < 0 || e.RowIndex == dataGridView1.NewRowIndex)
return;
BeginInvoke(new Action(() =>
{
var textBox = dataGridView1.EditingControl as DataGridViewTextBoxEditingControl;
if (textBox != null)
{
SetEditingControlColor(textBox);
}
}));
}
private void dataGridView1_CellPainting(object sender,
DataGridViewCellPaintingEventArgs e)
{
if (e.ColumnIndex < 0 || e.RowIndex < 0 || e.RowIndex == dataGridView1.NewRowIndex)
return;
var drv = dataGridView1.Rows[e.RowIndex].DataBoundItem as DataRowView;
if (drv != null && drv.Row.HasVersion(DataRowVersion.Original))
{
var column = dataGridView1.Columns[e.ColumnIndex].DataPropertyName;
if (drv.Row[column, DataRowVersion.Current]
.Equals(drv.Row[column, DataRowVersion.Original]))
{
e.CellStyle.BackColor = Color.White;
}
else
{
e.CellStyle.BackColor = Color.Yellow;
}
return;
}
e.CellStyle.BackColor = Color.LimeGreen;
}
void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
var textBox = e.Control as DataGridViewTextBoxEditingControl;
if (textBox != null)
{
textBox.TextChanged -= textbox_TextChanged;
textBox.TextChanged += textbox_TextChanged;
}
}
private void textbox_TextChanged(object sender, EventArgs e)
{
var textBox = (DataGridViewTextBoxEditingControl)sender;
SetEditingControlColor(textBox);
}
void SetEditingControlColor(DataGridViewTextBoxEditingControl textBox)
{
var dgv = textBox.EditingControlDataGridView;
var drv = dgv.CurrentCell.OwningRow.DataBoundItem as DataRowView;
if (drv != null && drv.Row.HasVersion(DataRowVersion.Original))
{
var column = dgv.Columns[dgv.CurrentCell.ColumnIndex].DataPropertyName;
var value = drv.Row[column, DataRowVersion.Original];
if (textBox.Text.Equals($"{value}"))
{
textBox.BackColor = Color.White;
textBox.Parent.BackColor = Color.White;
}
else
{
textBox.BackColor = Color.Yellow;
textBox.Parent.BackColor = Color.Yellow;
}
return;
}
textBox.BackColor = Color.LimeGreen;
textBox.Parent.BackColor = Color.LimeGreen;
}
Upvotes: 1