DataTable.GetChanges()返回null

时间:2014-07-31 16:25:24

标签: winforms c#-4.0 datagridview

我有一个DataGridView,它有一个DataGridViewCheckBoxColumn。我试图让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事件处理程序,所有代码都在事件处理程序中正确执行,但当我单击save而不更改单元格焦点时,.GetChanges()仍为null。我的理解是CurrentCellDirtyStateChanged事件处理程序是对此的修复。现在我真的很难过。代码示例更新以反映新的更改。

1 个答案:

答案 0 :(得分:0)

好的,找到了解决方案。我遇到了一个很棒的小助手方法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();
        }
    }
}

我仍然感到困惑,为什么原始代码不起作用。其他具有相同类型问题的海报似乎也取得了成功。如果有人能向我解释这将是伟大的。