Reputation: 73
I made a test form that contains a DataGridView control. There is also a ToolStrip with a "Save" button on it. Below is the used code:
public partial class TestForm7 : Form
{
BindingSource bs;
DataTable dt;
SqlDataAdapter da;
SqlCommandBuilder cb;
public TestForm7()
{
InitializeComponent();
}
private void TestForm7_Load(object sender, EventArgs e)
{
da = new SqlDataAdapter("select * from Bills", AppConnections.GetSqlConnection());
dt = new DataTable("Bills");
cb = new SqlCommandBuilder(da);
da.Fill(dt);
bs = new BindingSource();
bs.DataSource = dt;
dataGridView1.DataSource = bs;
}
private void toolStripButtonSave_Click(object sender, EventArgs e)
{
DataRow dr = ((DataRowView)bs.Current).Row;
DataGridViewCell currentCell = dataGridView1.CurrentCell as DataGridViewCell;
if (currentCell.IsInEditMode)
{
dataGridView1.EndEdit();
}
bs.EndEdit();
da.Update(dt);
}
}
I witness an odd behavior of my DataGridView control that puzzles me.
The following pattern is OK:
The form opens, the first record gets current. The value of a target test cell is “a”. I change the value to “b”. Then without changing the record I move focus to another cell. Then I press ESC, which causes the value of my target test cell change back to its original value of “a”.
The described above is a default behavior in such cases.
The following order of actions causes me troubles:
The form opens, the first record gets current. The value of a target test cell is “a”. I change the value to “b” and click “Save” button. The record gets saved in a database. Then without changing the current cell I enter “c” to the cell and move focus to another cell in the same record. Now I expect that pressing ESC will return “b” as a cell value but that won’t happen!!! I can press ESC how many times I want but that’ll change nothing because for some unknown reason the Row.State changed from Unchanged to Modified.
Why is that? What causes Row.State change is value? That’s abnormal but I don’t know what to do. I need ESC to bring back the original value. Do you have any ideas how to achieve that?
I noticed that if after clicking “Save” button I change the current record and then return back to it carrying out the described above actions then everything will be all right.
Sergiy Vakshul
Upvotes: 1
Views: 5271
Reputation: 73
I see that my explanation wasn’t plain enough.
Let me expound on it a bit longer.
Behavior by design.
Activate the 5th cell in a row.
Before editing the row we have:
dr[4].ToString() = “”
dr.RowState = Unchanged
dr.HasVersion(DataRowVersion.Proposed) = false
Enter “ddd” to the current sell, but do not commit editing. We have:
dr[4].ToString() = “”
dr.RowState = Unchanged
dr.HasVersion(DataRowVersion.Proposed) = false
Move focus to another cell of the same row. We have:
dr[4].ToString() = “ddd”
dr.RowState = Unchanged
dr.HasVersion(DataRowVersion.Proposed) = true
Press ESC. We have:
dr[4].ToString() = “”
dr.RowState = Unchanged
dr.HasVersion(DataRowVersion.Proposed) = false
So, that was behavior by design.
Let’s get back to my code.
Activate the 5th cell in a row.
Before editing the row we have:
dr[4].ToString() = “”
dr.RowState = Unchanged
dr.HasVersion(DataRowVersion.Proposed) = false
Enter “ddd” to the current sell and click Save button to debug the code. After
dataGridView1.EndEdit();
We have:
dr[4].ToString() = “ddd”
dr.RowState = Unchanged
dr.HasVersion(DataRowVersion.Proposed) = true
Then after
bs.EndEdit();
We have:
dr[4].ToString() = “ddd”
dr.RowState = Modified
dr.HasVersion(DataRowVersion.Proposed) = false
Then after
da.Update(dt);
We have:
dr[4].ToString() = “ddd”
dr.RowState = Unchanged
dr.HasVersion(DataRowVersion.Proposed) = false
I’d like to draw your attention to the fact that now we are at the same state as we were before the editing. I mean that there are no visible pending changes left: dr.RowState is Unchanged and dr.HasVersion(DataRowVersion.Proposed) is false.
The next important thing is that you mustn’t change the current row if you want to reproduce the abnormal effect I am talking about. So, let’s continue editing the same row.
Enter “aaa” to the current sell , but do not commit editing.
We have:
dr[4].ToString() = “ddd”
dr.RowState = Unchanged
dr.HasVersion(DataRowVersion.Proposed) = false
Move focus to another cell of the same row. We have:
dr[4].ToString() = “aaa”
dr.RowState = Modified
dr.HasVersion(DataRowVersion.Proposed) = false
Press ESC. We have:
dr[4].ToString() = “aaa”
dr.RowState = Modified
dr.HasVersion(DataRowVersion.Proposed) = false
See what I mean?
We didn’t move focus to another row nor did we committed editing the row. Notwithstanding that, RowState changed from Unchanged to Modified. No wonder pressing ESC was of no help anymore.
So this behavior definitely isn’t by design.
Remember me saying that
you mustn’t change the current row if you want to reproduce the abnormal effect I am talking about?
Remarkably, if just after clicking Save button you change the current row and then get back to that row again then DataGridView will behave by design indeed.
So, I still need help – how to avoid the unwanted effect? To put the question more broadly: how to save a row without any side effects?
Upvotes: 0
Reputation: 2781
That's normal behavior and it's by design. You can undo changes only for the current item.
Why it so? It's because when you are changing the current row the edited row commits changes, i.e. IEditableObject.EndEdit
is called.
And because the CurrencyManager
has no public constructor there is no way to change the standard behavior except implementing your own view for a DataTable
which is not easy.
Upvotes: 1