C
Chris Shepherd
Here's the scenario:
I have a form, with an unknown dataset (could be ObjectDataSource,
DataTable, etc.) which populates a DataGridView. I need to cache prior
values from a row on the DataGridView before updating them with current
values from the DB, and then do some specific things if particular
columns have changed. This form may be open across several hours. An
example of what I'd like to do is change the DataGridViewRow's
background colour based on the amount of time until a task is supposed
to occur.
According to the documentation at MSDN regarding the Clone method of
DataGridViewRow:
"Creates an exact copy of this row.
Namespace: System.Windows.Forms
Assembly: System.Windows.Forms (in system.windows.forms.dll)
[... Syntax section snipped ...]
Return Value
An Object that represents the cloned DataGridViewRow.
RemarksRemarks
The Clone method copies the row and its property values, but does not
copy the cell values that the row contains. For information about how to
copy cell values when cloning a row, see the example section.
Override the Clone method whenever you derive from DataGridViewRow and
add new properties to the derived class."
Now, the problem I'm having is that the original row has all the proper
values, and importantly, I can reference the cells by the underlying
table's column name but with the cloned version I cannot. I'm guessing
this is because the cloned row doesn't know about the underlying
bindings. Any suggestions on the workaround, keeping in mind I have no
idea what the underlying DataSource might be?
Simple but functional example:
From the Form1.cs --all that's in the designer files is just a default
new form with a fill-docked DatagGridView named "grid" and the listener
for CellContentClick on said grid. The last line of
grid_CellContentClick is where it breaks with "could not find column
named 'Name'":
public partial class Form1 : Form
{
private DataTable someTable;
public Form1()
{
InitializeComponent();
grid.AllowUserToAddRows = false;
someTable = new DataTable();
someTable.Columns.Add("Name");
someTable.Columns.Add("Email");
someTable.Columns.Add("SomeFlag");
someTable.Rows.Add("Joe Test", "(e-mail address removed)", true);
someTable.Rows.Add("Tim Test", "(e-mail address removed)", false);
someTable.Rows.Add("Ted Test", "(e-mail address removed)", false);
}
private void Form1_Load(object sender, EventArgs e)
{
Console.WriteLine(someTable.Rows.Count.ToString());
grid.DataSource = someTable;
}
private void grid_CellContentClick(object sender,
DataGridViewCellEventArgs e)
{
DataGridViewRow newRow = grid.Rows[e.RowIndex];
DataGridViewRow cachedRow = (DataGridViewRow)newRow.Clone();
for (Int32 index = 0; index < newRow.Cells.Count; index++)
cachedRow.Cells[index].Value =
newRow.Cells[index].Value;
newRow.Cells["SomeFlag"].Value = false;
Console.WriteLine("{0}: {1}",
newRow.Cells["Name"].Value.ToString(),
newRow.Cells["SomeFlag"].Value.ToString());
Console.WriteLine("{0}: {1}",
cachedRow.Cells["Name"].Value.ToString(),
cachedRow.Cells["SomeFlag"].Value.ToString());
}
}
I have a form, with an unknown dataset (could be ObjectDataSource,
DataTable, etc.) which populates a DataGridView. I need to cache prior
values from a row on the DataGridView before updating them with current
values from the DB, and then do some specific things if particular
columns have changed. This form may be open across several hours. An
example of what I'd like to do is change the DataGridViewRow's
background colour based on the amount of time until a task is supposed
to occur.
According to the documentation at MSDN regarding the Clone method of
DataGridViewRow:
"Creates an exact copy of this row.
Namespace: System.Windows.Forms
Assembly: System.Windows.Forms (in system.windows.forms.dll)
[... Syntax section snipped ...]
Return Value
An Object that represents the cloned DataGridViewRow.
RemarksRemarks
The Clone method copies the row and its property values, but does not
copy the cell values that the row contains. For information about how to
copy cell values when cloning a row, see the example section.
Override the Clone method whenever you derive from DataGridViewRow and
add new properties to the derived class."
Now, the problem I'm having is that the original row has all the proper
values, and importantly, I can reference the cells by the underlying
table's column name but with the cloned version I cannot. I'm guessing
this is because the cloned row doesn't know about the underlying
bindings. Any suggestions on the workaround, keeping in mind I have no
idea what the underlying DataSource might be?
Simple but functional example:
From the Form1.cs --all that's in the designer files is just a default
new form with a fill-docked DatagGridView named "grid" and the listener
for CellContentClick on said grid. The last line of
grid_CellContentClick is where it breaks with "could not find column
named 'Name'":
public partial class Form1 : Form
{
private DataTable someTable;
public Form1()
{
InitializeComponent();
grid.AllowUserToAddRows = false;
someTable = new DataTable();
someTable.Columns.Add("Name");
someTable.Columns.Add("Email");
someTable.Columns.Add("SomeFlag");
someTable.Rows.Add("Joe Test", "(e-mail address removed)", true);
someTable.Rows.Add("Tim Test", "(e-mail address removed)", false);
someTable.Rows.Add("Ted Test", "(e-mail address removed)", false);
}
private void Form1_Load(object sender, EventArgs e)
{
Console.WriteLine(someTable.Rows.Count.ToString());
grid.DataSource = someTable;
}
private void grid_CellContentClick(object sender,
DataGridViewCellEventArgs e)
{
DataGridViewRow newRow = grid.Rows[e.RowIndex];
DataGridViewRow cachedRow = (DataGridViewRow)newRow.Clone();
for (Int32 index = 0; index < newRow.Cells.Count; index++)
cachedRow.Cells[index].Value =
newRow.Cells[index].Value;
newRow.Cells["SomeFlag"].Value = false;
Console.WriteLine("{0}: {1}",
newRow.Cells["Name"].Value.ToString(),
newRow.Cells["SomeFlag"].Value.ToString());
Console.WriteLine("{0}: {1}",
cachedRow.Cells["Name"].Value.ToString(),
cachedRow.Cells["SomeFlag"].Value.ToString());
}
}