Reputation:
How to fix CellFormatting
"slow scrolling" performance issue?
Using this code to copy decrypted values from encrypted column to another column:
private void grid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (e.ColumnIndex < 0 || e.RowIndex < 0)
return;
var columnB = grid.Columns[e.ColumnIndex];
if (columnB.Name != "B")
return;
var value = grid.Rows[e.RowIndex].Cells["A"].Value;
if (value == null || value == DBNull.Value)
return;
e.Value = Decrypt(value.ToString());
}
Upvotes: 3
Views: 2394
Reputation: 37633
Dont use CellFormating
method at all.
I found very well working solution finally.
Here is my code.
dgvTrucksMaster.SuspendLayout();
dgvTrucksMaster.DataSource = calendar.FailureCalendarDetails.OrderBy(x => x.MachineFullName).ToList();
foreach (DataGridViewRow row in dgvTrucksMaster.Rows)
{
if (Convert.ToDouble(row.Cells["Decade1Hours"].Value) > 0)
{
row.Cells["Decade1Hours"].Style.BackColor = Color.LightGreen;
}
if (Convert.ToDouble(row.Cells["Decade1Hours"].Value) < 0)
{
// row.DefaultCellStyle.BackColor = Color.LightSalmon;
row.Cells["Decade1Hours"].Style.BackColor = Color.LightSalmon;
}
if (Convert.ToDouble(row.Cells["Decade2Hours"].Value) > 0)
{
row.Cells["Decade2Hours"].Style.BackColor = Color.LightGreen;
}
if (Convert.ToDouble(row.Cells["Decade2Hours"].Value) < 0)
{
// row.DefaultCellStyle.BackColor = Color.LightSalmon;
row.Cells["Decade2Hours"].Style.BackColor = Color.LightSalmon;
}
if (Convert.ToDouble(row.Cells["Decade3Hours"].Value) > 0)
{
row.Cells["Decade3Hours"].Style.BackColor = Color.LightGreen;
}
if (Convert.ToDouble(row.Cells["Decade3Hours"].Value) < 0)
{
// row.DefaultCellStyle.BackColor = Color.LightSalmon;
row.Cells["Decade3Hours"].Style.BackColor = Color.LightSalmon;
}
if (Convert.ToDouble(row.Cells["DecadeMonthHours"].Value) > 0)
{
row.Cells["DecadeMonthHours"].Style.BackColor = Color.LightGreen;
}
if (Convert.ToDouble(row.Cells["DecadeMonthHours"].Value) < 0)
{
// row.DefaultCellStyle.BackColor = Color.LightSalmon;
row.Cells["DecadeMonthHours"].Style.BackColor = Color.LightSalmon;
}
for (int i = 0; i < 61; i++)
{
if (Convert.ToDouble(row.Cells[string.Format("D{0}", i + 1)].Value) < 0)
{
row.Cells[string.Format("D{0}", i + 1)].Style.BackColor = Color.LightSalmon;
}
if (Convert.ToDouble(row.Cells[string.Format("D{0}", i + 1)].Value) > 0)
{
row.Cells[string.Format("D{0}", i + 1)].Style.BackColor = Color.LightGreen;
}
}
}
dgvTrucksMaster.ResumeLayout();
As you see from the code the key is to change CellFormating
after you apply Data Source
and before ResumeLayout
method.
Just try it and you will satisfy with result.
Oh! And make sure you do it within BeginInvoke((Action)(() => { // Some code });
code. So please get and prepare Data Source
asynchronously.
Upvotes: 1
Reputation: 125197
If the performance issue is because of Decrypt
method, you should avoid using it in CellFormatting
as mentioned in remarks part of the event's documentations:
The
CellFormatting
event occurs every time each cell is painted, so you should avoid lengthy processing when handling this event.
what solution can I use to provide value for the second column based on first column?
You can use either of these options:
DataGridView
and provide the value in a for loop.DataTable
) and provide the value in a for loop.Example
In the below example, it doesn't make any difference if you load data from database. But to provide a minimal complete verifiable example, I created DataTable
myself. In both examples LoadData
method, loads a DataTable
:
private DataTable LoadData()
{
var dt = new DataTable();
dt.Columns.Add("ExistingColumn");
dt.Rows.Add("x");
dt.Rows.Add("y");
dt.Rows.Add("z");
return dt;
}
Example 1 - Add Column To DataGridView
var dt = LoadData();
dataGridView1.DataSource = dt;
//Add new column to DataGridView
var newColumn = new DataGridViewTextBoxColumn();
newColumn.HeaderText = "NewColumn";
newColumn.Name = "NewColumn";
dataGridView1.Columns.Add(newColumn);
//Copy Values
foreach (DataGridViewRow r in this.dataGridView1.Rows)
{
if(!r.IsNewRow)
r.Cells["NewColumn"].Value = Decrypt(r.Cells["ExistingColumn"].Value.ToString());
}
Example 2 - Add Column to DataTable
var dt = LoadData();
dataGridView1.DataSource = dt;
//Add new column to DataTable
dt.Columns.Add("NewColumn");
//Copy Values
foreach (DataRow r in dt.Rows)
r["NewColumn"] = Decrypt(r.Field<string>("ExistingColumn");
Upvotes: 3