I have a DGV that has some conditional formatting for values in all columns but the first N columns (Item columns). The first N columns (Category columns)have reference values for the rest of the table. Something like that:
Category1 Category2 Item1 Item2 Item3 Item4
1 2 1 2 1 2
56 57 57 56 56 56
I also have a dictionary that sets correspondence of headers of all the columns to the headers of the reference columns.
{Item1, Category1}
{Item2, Category1}
{Item3, Category1}
{Item4, Category2}
Each cell for Items1-4 is compared to the corresponding Category (using Dictionary) in the CellFormatting Event Handler, Then if it's a match, it colors the cell green, otherwise - red.
In other words, in the handler of CellFormatting event I use dictionary to check what values a particular column should have from N Reference columns.
Now I have a completely separate control (another DGV with comboboxes) that allows user to change that dictionary (switch what Category each Item belongs). How do I manually raise CellFormatting event when I change that dictionary?
This is my Event Handler for Cell Formatting:
private void dataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
try
{
if (e.ColumnIndex > N_of_ReferenceColumns)
{
if (e.Value.ToString() == this.dataGridView.Rows[e.RowIndex].Cells[dataGridView.Columns[convertItemToCategory(dataGridView.Columns[e.ColumnIndex].Name)].Index].Value.ToString())
{
e.CellStyle.BackColor = Color.Green;
e.CellStyle.SelectionBackColor = Color.DarkGreen;
}
else
{
e.CellStyle.BackColor = Color.Red;
e.CellStyle.SelectionBackColor = Color.DarkRed;
}
}
}
catch
{ }
}
And this is my Handler on changing values in Combobox for Category for each of the Items:
private void DictionarydataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
UpdateDictionary(DictionarydataGridView.Rows[e.RowIndex].Cells[1].Value.ToString(), DictionarydataGridView.Rows[e.RowIndex].Cells[0].Value.ToString());
}
And this is how I update my dictionary and how I use it in conditional formatting logic:
public static IDictionary<string, string> Dictionary = new Dictionary<string, string>();
public void UpdateDictionary(string key, string value)
{
Dictionary[key] = value;
}
public static string convertItemToCategory(string key)
{
string value = "";
if (Dictionary.TryGetValue(key.ToUpper(), out value))
{
return value;
}
else
{
return key.ToUpper();
}
}
What I need to do is when I update Dictionary, also raise CellFormatting event so that conditional formatting updates based on new selection.
One way would be to pack logic of update into a separate method, and then call it separately form each event handler, I'm not sure though what to do with all the e.CellStyle.BackColor and so on...
Any ideas?
A quick hack that never fails is to force the data grid to re-bind to the data source by resetting the data source.
This thread has lengthy discussions on the topic: C# refresh DataGridView when updating or inserted on another form
You could put a helper method on the form:
public void Refresh()
{
datagridview1.DataSource = datagridview1.DataSource; // should re-evaluate all logic related to data bindings
datagridview1.Refresh(); // forces the control to repaint
}
It's probably the most intensive solution but it should do the job.