DataTable.GetChanges() 返回 null

Posted

技术标签:

【中文标题】DataTable.GetChanges() 返回 null【英文标题】:DataTable.GetChanges() returns null 【发布时间】:2014-07-31 16:25:24 【问题描述】:

我有一个具有 DataGridViewCheckBoxColumn 的 DataGridView。我试图让 DataSource 更新,以便我可以检索 DataTable 的更改以保存到数据库中。我在这里和其他网站上阅读了几篇文章,但我还没有成功。我发现 CurrentCellDirtyStateChange 事件必须在 CellContentClick 事件之后执行,以避免必须从物理上移出 DataGridViewCheckBoxColumn Cell 以获取底层数据源以获取更改。如果我离开单元格,我将成功检索 .GetChanges()。问题是 CurrentCellDirtyStateChange 永远不会触发。我错过了什么?正确的处理程序在 .designer.cs 文件中定义。

private void saveChangesToolStripMenuItem_Click(object sender, EventArgs e)

    DataTable dt = fileData.GetChanges();
    if (dt == null)  return; 

    foreach (DataRow row in dt.Rows)
    
        if (row.Field<int>("Id") != null)
        
            if (row.Field<bool>("Selected"))
            
                // update
            
            else
            
                // delete
            
        
        else
        
            // add 
        
    

    fileData.AcceptChanges();
    dgvColumnValues.ResetBindings();



private void dgvColumnValues_CellContentClick(object sender, DataGridViewCellEventArgs e)

    if (e.ColumnIndex != dgvColumnValues.Columns["Selected"].Index) return;

    dgvColumnValues.BeginEdit(true);
    dgvColumnValues.CurrentCell.Value = !(bool) dgvColumnValues.CurrentCell.Value;
    dgvColumnValues.NotifyCurrentCellDirty(true);
    dgvColumnValues.EndEdit();
    bsAcceptableColumn.EndEdit();



private void dgvColumnValues_CurrentCellDirtyStateChanged(object sender, EventArgs e)

    if (dgvColumnValues.IsCurrentCellDirty)
    
        dgvColumnValues.CommitEdit(DataGridViewDataErrorContexts.Commit);
    

更新: 即使只是绕过 IsCurrentCellDirty 检查并调用 dgvColumnValues.CommitEdit(DataGridViewDataErrorContexts.Commit); .GetChanges() 仍然返回 null。

更新: 我想出了如何通过调用 dgvColumnValues.NotifyCurrentCellDirty(true); 来调用 CurrentCellDirtyStateChanged 事件处理程序,所有代码都在事件处理程序中正确执行,但是当我单击保存而不更改单元格焦点时 .GetChanges() 仍然为空。我的理解是 CurrentCellDirtyStateChanged 事件处理程序是解决这个问题的方法。现在我真的很难过。代码示例更新以反映新的变化。

【问题讨论】:

看看我对这个问题***.com/questions/22284280/…的回答是否有帮助。 这没有帮助。它所做的只是将我已经在 CellContentClick 事件处理程序中使用的 datagridview 的 .EndEdit() 移动到 CurrentCellDirtyStateChanged 事件处理程序中。 .GetChanges() 仍然为空。 【参考方案1】:

好的,找到解决方案。我遇到了一个很棒的小助手方法here。博客文章对发生的事情进行了一些深入的介绍。该方法是为 DataSet 编写的,但我将其修改为 DataTable 以满足我的需要。所以完整的工作代码如下...

private void saveChangesToolStripMenuItem_Click(object sender, EventArgs e)

    CommitProposedChanges((DataTable)dgvColumnValues.DataSource);
    DataTable dt = ((DataTable)dgvColumnValues.DataSource).GetChanges();
    if (dt == null)  return; 

    foreach (DataRow row in dt.Rows)
    
        if (row.Field<int>("Id") != null)
        
            if (row.Field<bool>("Selected"))
            
                // update
            
            else
            
                // delete
            
        
        else
        
            // add this row to the table
        
    

    ((DataTable)dgvColumnValues.DataSource).AcceptChanges();
    dgvColumnValues.ResetBindings();


private void dgvColumnValues_CellContentClick(object sender, DataGridViewCellEventArgs e)

    if (e.ColumnIndex != dgvColumnValues.Columns["Selected"].Index) return;
    DataGridViewCheckBoxCell cell = (DataGridViewCheckBoxCell)((DataGridView)sender).Rows[e.RowIndex].Cells[e.ColumnIndex];
    if (cell.ValueType != typeof(bool)) return;
    cell.Value = !(bool)cell.Value;

    dgvColumnValues.EndEdit();


protected virtual void CommitProposedChanges(DataTable dt)

    if (dt == null) return;

    for (int nRow = 0; nRow < dt.Rows.Count; nRow++)
    
        if (dt.Rows[nRow].HasVersion(DataRowVersion.Proposed))
        
            dt.Rows[nRow].EndEdit();
        
    

我仍然对为什么原始代码不起作用感到困惑。其他具有相同类型问题的海报似乎也取得了成功。如果有人可以向我解释,那就太好了。

【讨论】:

以上是关于DataTable.GetChanges() 返回 null的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin 协程Flow 异步流 ① ( 以异步返回返回多个返回值 | 同步调用返回多个值的弊端 | 尝试在 sequence 中调用挂起函数返回多个返回值 | 协程中调用挂起函数返回集合 )

使用fiddler修改返回值以及返回状态码

Android开发如何点击物理返回键返回上个界面

Javascript:嵌套返回语句,返回内部返回

Android——关于Activity跳转的返回(无返回值和有返回值)——无返回值

JAVA里的函数返回值,可以返回几个?