2

我有一个带有位列的 DataGridView,它显示为一个复选框。该列的名称为“IsDefault”,表示如果选中此单元格,则 DataTable 中此列中的所有其他单元格都应取消选中(仅允许此列中的 1 个单元格为默认值)。

我设法通过处理 DataGridView 的 CellContentClick 事件中的更改来使这种行为起作用,即:

private void ViewIconsDataGrid_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    if (e.RowIndex == -1 || e.ColumnIndex == -1)
        return;

    DataTable table = ViewIconsDataGrid.DataSource as DataTable;
    DataGridViewCell cell = ViewIconsDataGrid.Rows[e.RowIndex].Cells[e.ColumnIndex];
    Guid rowID = (Guid)ViewIconsDataGrid.Rows[e.RowIndex].Cells["ID"].Value;

    if (cell.GetType() == typeof(DataGridViewCheckBoxCell))
    {
        DataGridViewCheckBoxCell checkBoxCell = cell as DataGridViewCheckBoxCell;

        bool value = (bool)checkBoxCell.EditedFormattedValue, previous = (bool)checkBoxCell.Value;

        if (value != previous)
        {
            if (value == true)
            {
                Guid currentDefault;

                if(MyIcons.Defaults.TryGetValue(MyGroupID, out currentDefault))
                {
                    DataRow [] rows = table.Select("ID = '" + currentDefault.ToString() + "'");

                    if(rows.Length == 1)
                    {
                        rows[0]["IsDefault"] = false;
                    }
                }
            }

            ViewIconsDataGrid.EndEdit(); table.AcceptChanges();
        }
    }
}

现在,显然我正在尝试更改同一 DataTable 中的两条记录。首先我希望 DataGridView 发生变化(当用户更改复选框的状态时),然后我在 DataTable 上进行另一项更改以取消选中已经进行检查的任何行,希望它将传播到 DataGridView。当然,我需要将这两项更改都提交到数据库。

这是我的数据库“更新”代码,它是一种通用的,即我传入整个表的选择查询和要更新的数据表:

using (SqlConnection connection = new SqlConnection(ConfigurationManager.AppSettings["Connection"]))
{
    connection.Open();

    using (SqlDataAdapter adapter = new SqlDataAdapter(MyQuery, connection))
    {
        adapter.InsertCommand = new SqlCommandBuilder(adapter).GetInsertCommand();
        adapter.DeleteCommand = new SqlCommandBuilder(adapter).GetDeleteCommand();
        adapter.UpdateCommand = new SqlCommandBuilder(adapter).GetUpdateCommand();

        adapter.Update(MyTable);
    }
}

所以,问题是当我在进行这些更改后尝试更新表时出现异常:“并发冲突:UpdateCommand 影响了预期的 1 条记录中的 0 条。”。如果没有现有的默认值,则只会更新一条记录,一切都很好。

谁能发现我的错误,或者找到一种更简单的方法来做到这一点?

编辑 1:在上面的片段中,MyQuery如下所示:

@"SELECT * From Picture WHERE ID_Group = '{0}' AND Deleted = 0 ORDER BY Created DESC

{0} 是我正在更新的图片组的 guid,即选择查询提供图片表中属于该组成员的所有记录。

4

2 回答 2

3

调用将表中每一行的 更改为未更改AcceptChanges。 随后对 DataAdatper.Update(table) 的调用找不到任何要更新/插入或删除的内容。RowState

您需要在用户输入时调用更新(例如单击保存按钮)

编辑 使用@Robinson 的以下发现完成此答案

RowChanged您可以为处理事件的表引发CurrentCellDirtyStateChanged事件并在 DataGridView 上手动提交编辑。否则,当行失去焦点时会引发 RowChanged 事件。

于 2013-06-05T12:24:09.347 回答
0

这里有两个问题

首先,DataGridView 事件不会发送以正确缓存更改,您必须使用其他事件(例如按钮单击)来强制 DataGridView 缓存更改。

另一个问题“并发冲突”是由在具有标识列(通常是主键)的表中插入新行引起的。我建议使用另一个按钮进行插入并在 DataGridView 中强制使用新的标识值。

当您更新时,我建议先进行删除,然后再进行更新:

// First process deletes.
da.Update(dt.Select(null, null, DataViewRowState.Deleted));

// Next process updates.
da.Update(dt.Select(null, null, DataViewRowState.ModifiedCurrent));
于 2016-12-15T12:08:39.343 回答