【问题标题】:DataGridView editable cell input overwritten when another cell is updated更新另一个单元格时覆盖 DataGridView 可编辑单元格输入
【发布时间】:2016-05-17 16:53:04
【问题描述】:

我有一个通过BindingSource 绑定到DataTableDataGridView,并且我的网格有用户输入值的可编辑列,还有一些以编程方式实时更新的只读列(想想就像股票行情一样)。对于以编程方式更新的列,我正在更新 DataTable 中的值,然后由于数据绑定而更新 DataGridView 中的值。 我遇到的问题是,当用户编辑一个单元格时,如果以编程方式更新另一个单元格,则用户在第一个单元格中输入的文本会被覆盖(在编辑之前重置为单元格的值)。

这对我来说似乎不是什么不寻常的情况,但我似乎无法让它正常工作。任何人都知道我可能做错了什么,或者可以指出一个示例来说明如何正确执行此操作?

【问题讨论】:

  • 程序化更新的列,这是在计时器中发生还是如何发生?我认为您需要在用户编辑时禁用以编程方式更新,因为它看起来像是更新了整个记录,因此重置了用户输入的任何内容。您可能会考虑不使用绑定来填充您的数据网格视图,而是自己完成所有操作,这样您就可以控制哪些单元格被编程更新而哪些不是。
  • 我没有开发系统的那部分,但我相信有一个后台线程一直在等待从 PUSH 服务器接收 PUSH 更新,然后当它收到更新时它会调用一个方法在 UI 线程上更新相应的 DataTable。

标签: c# winforms data-binding datagridview datagrid


【解决方案1】:

这是因为当DataTable 中的基础值发生变化时,DataGridView.DataBindingComplete 事件被触发 - 重置绑定。

My first suggestion 是您捕获此事件并检查CurrentCellEditedFormattedValue 是否与Value 不同 - 如果是,则设置Value。这有效——直到我检查了第一行——这完全忽略了我的逻辑。

我能找到始终有效的唯一解决方案是更改程序化实时更新的发生方式。如果可能,不要更新 DataTable 列,而只需更新 DataGridView 列。这些更改将延续到源,但绑定不会重置 - 因此您当前的编辑单元格不会丢失任何更改。

罢工>

foreach (DataRow row in this.table.Rows)
{
    row[1] = someNewValue;
}

foreach (DataGridViewRow row in this.dataGridView1.Rows)
{
    row.Cells[1].Value = someNewValue;
}

【讨论】:

  • 我尝试了您的建议,但由于某种原因 DataGridView.DataBindingComplete 并不总是触发。有时它会按预期触发,但有时即使我可以看到屏幕上的值发生变化,它也不会运行我的 DataBindingComplete 处理程序...
  • 这是我之前的建议,在我发现使用 DataBindingComplete 的解决方案存在缺陷之前。相反,如果可能,只需将您对只读列进行编程更新的方式更改为我的建议(即设置 DataGridViewCell 值而不是基础 DataTable 单元格值)。
  • 不幸的是,无法设置 DataGridViewCell 值,因为以编程方式更新的列在后台直接在 DataTable 上更新,更改通过数据绑定传播到 DataGridView。
  • 啊,真不幸。我之前的解决方案几乎适用于这种情况,除了第一行拒绝工作 - 并且包含编辑单元格的行的其他单元格在您完成编辑当前单元格之前不会更新。当我有更多空闲时间时,我会继续研究它。
【解决方案2】:

最后我解决了,所以我会在这里添加我的解决方案,以防它对其他人有帮助。

我处理了DataGridViewCellBeginEditCellEndEditCurrentCellDirtyStateChanged事件并添加了以下代码:

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 保存编辑前单元格的值(在DataGridViewCellBeginEdit 事件处理程序中设置)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多