DataGridView 可编辑单元格输入在更新另一个单元格时被覆盖
本文关键字:单元格 另一个 覆盖 更新 编辑 输入 DataGridView | 更新日期: 2023-09-27 18:33:48
我有一个通过BindingSource
绑定到DataTable
的DataGridView
,我的网格有用户输入值的可编辑列,还有一些以编程方式实时更新的只读列(像股票行情一样思考)。 对于以编程方式更新的列,我正在更新DataTable
中的值,然后由于数据绑定而更新 DataGridView 中的值。我遇到的问题是,当用户编辑一个单元格时,如果以编程方式更新另一个单元格,则用户在第一个单元格中输入的文本将被覆盖(在编辑之前重置为单元格的值)。
这对我来说似乎不是一个不寻常的情况,但我似乎无法让它正常工作。 有谁知道我可能做错了什么,或者可以指出我一个展示如何正确做到这一点的例子?
是因为当DataTable
中的基础值更改时,将触发DataGridView.DataBindingComplete
事件 - 重置绑定。
我的第一个建议是捕获此事件并检查CurrentCell
的EditedFormattedValue
是否与Value
不同 - 如果是,则设置Value
。这有效 - 直到我检查第一行 - 这完全忽略了我的逻辑。
我能找到的唯一解决方案是改变程序化实时更新的发生方式。如果可能,只需更新DataGridView
列,而不是更新DataTable
列。这些更改将永久保存到源,但绑定不会重置 - 因此您当前的编辑单元格不会丢失任何更改。
foreach (DataRow row in this.table.Rows)
{
row[1] = someNewValue;
}
foreach (DataGridViewRow row in this.dataGridView1.Rows)
{
row.Cells[1].Value = someNewValue;
}
最后我解决了这个问题,所以我将在此处添加我的解决方案,以防它对其他人有所帮助。
我处理了DataGridView
的CellBeginEdit
、CellEndEdit
和CurrentCellDirtyStateChanged
事件,并添加了以下代码:
private void Grid_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
((DataRowView)((DataGridView)sender).Rows[e.RowIndex].DataBoundItem).BeginEdit();
}
private void Grid_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
// need this check for when the program is closed while a cell is in edit mode
// otherwise an IndexOutOfRangeException occurs
if (((BindingSource)((DataGridView)sender).DataSource).List.Count > e.RowIndex)
((DataRowView)((DataGridView)sender).Rows[e.RowIndex].DataBoundItem).EndEdit();
}
private void Grid_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
// commit changes to the table as soon as they are entered so they don't
// get overwritten when the DataTable is updated
if (Grid.IsCurrentCellDirty)
Grid.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
我还发现DataGridView
的 Esc 键功能不仅恢复了对当前处于编辑模式的单元格的更改,而且还恢复了直接在DataTable
中设置值的更改(实时编程更新),因此我覆盖了DataGridView
的 Esc 键功能,如下所示:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (CurrentCell != null && CurrentCell.IsInEditMode)
{
if (keyData == (Keys.Escape))
{
CurrentCell.Value = valueBeforeEdit;
EditingControl.Text = valueBeforeEdit.ToString();
EndEdit();
return true;
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
其中valueBeforeEdit
在编辑之前保存单元格的值(在DataGridView
的CellBeginEdit
事件处理程序中设置)。