【问题标题】:How to determine if DataGridView contains uncommitted changes when bound to a SqlDataAdapter绑定到 SqlDataAdapter 时如何确定 DataGridView 是否包含未提交的更改
【发布时间】:2011-02-18 05:50:39
【问题描述】:

我有一个包含 DataGridView、BindingSource、DataTable 和 SqlDataAdapter 的表单。我按如下方式填充网格和数据绑定:

private BindingSource bindingSource = new BindingSource();
private DataTable table = new DataTable();
private SqlDataAdapter dataAdapter = new SqlDataAdapter("SELECT * FROM table ORDER BY id ASC;", ClassSql.SqlConn());
private void LoadData()
{
    table.Clear();
    dataGridView1.AutoGenerateColumns = false;
    dataGridView1.DataSource = bindingSource;
    SqlCommandBuilder commandBuilder = new SqlCommandBuilder(dataAdapter);
    table.Locale = System.Globalization.CultureInfo.InvariantCulture;
    dataAdapter.Fill(table);
    bindingSource.DataSource = table;
}

然后,用户可以对数据进行更改,并通过分别单击保存或取消按钮来提交或放弃这些更改。

private void btnSave_Click(object sender, EventArgs e)
{
    // save everything to the displays table
    dataAdapter.Update(table);
}

private void btnCancel_Click(object sender, EventArgs e)
{
    // alert user if unsaved changes, otherwise close form
}

如果存在未保存的更改,我想在单击取消时添加一个对话框,警告用户未保存的更改。

问题:

如何确定用户是否修改了 DataGridView 中的数据但未将其提交到数据库?有没有一种简单的方法可以将当前 DataGridView 数据与上次检索的查询进行比较? (请注意,不会有任何其他线程或用户同时更改 SQL 中的数据。)

【问题讨论】:

    标签: c# sql winforms


    【解决方案1】:

    为了检测 DataGridView 的变化,我最终使用了两个事件,CellValueChangedCurrentCellDirtyStateChanged(后者是由于复选框类型列)。

    当其中任何一个事件发生时,我设置一个布尔值 (UnsavedChanges) 以指示存在更改。当表单关闭或单击取消按钮(现在重命名为“Revert”)时,会检查布尔值,如果设置为 true,则会显示对话框。如果单击保存按钮,则布尔值设置为 false 并保存数据。

    虽然不像检查数据绑定或数据网格的一个属性那么简单,但它可以按需要工作。

    【讨论】:

    • 如果 UI 变得更复杂(每个表格有更多控件),这可能会出现问题。
    • 10 年后,经过几天对 stackoverflow 中多次建议的所有数据集和绑定源 getchanges() 函数的调查,这个简单的解决方案似乎是最有效的解决方案 - 所有其他解决方案都会失败,因为只需选择数据绑定数据网格视图中的单元格(不进行更改)将使数据集/绑定源认为已进行更改。
    【解决方案2】:

    这可能是一个愚蠢的问题,但为什么这不起作用?

    对于 VB

    Dim changes As DataTable = table.GetChanges()
            If changes.Rows.Count > 0 Then
                MessageBox.Show("You have unsaved edits!")
            End If
    

    对于 C#

    DataTable changes = table.GetChanges();
    if (changes.Rows.Count > 0)
        MessageBox.Show("You have unsaved edits!");
    

    如果您的数据表是通过绑定源绑定到您的 datagridview 的,那么您最近修改但未提交的编辑将挂在您的数据表中。数据集和数据表有一个GetChanges() 方法,可以进行艰苦的检查工作,并将编辑的内容准确地返回给您,仅此而已,并进行相应的操作。

    【讨论】:

    • 为我工作。确保测试“更改​​”变量以检查它是否为空(在测试 Rows.Count 值之前)。
    【解决方案3】:

    好吧,我正在玩一个技巧,希望它能对大家有所帮助,我正在使用 bindingsource 的 CurrentItemChanged 方法跟踪更改。这里我使用了 datagridview 的 tag 属性来标记更改,您可以使用变量:

       private void cONTRACTERBindingSource_CurrentItemChanged(object sender, EventArgs e)
            {
                if (cONTRACTERDataGridView.Tag==null)
                {
                    DataRow ThisDataRow =
                    ((DataRowView)((BindingSource)sender).Current).Row;
                    if (ThisDataRow.RowState == DataRowState.Modified)
                        cONTRACTERDataGridView.Tag = "1";
                }
            }
    

    请记住,这个触发器可以被触发很多次,因此两个 if 语句都控制一次运行,真的。最后,您可能会在退出按钮处理程序上使用此代码,因为在我的案例中代码在这里:

    private void btExit_Click(object sender, EventArgs e)
            {
                if (cONTRACTERDataGridView.Tag.Equals("1"))
                {
                    if (MessageBox.Show("Do you want to save the changes..!?", "Save Changes", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                        cONTRACTERBindingNavigatorSaveItem_Click(null, null);
                }
                this.Close();
            }
    

    在取消更改时,重置标志。希望它也对你有用。

    问候

    【讨论】:

      【解决方案4】:

      当处理带有数据集的小表格时,不想处理单元格更改事件并取消编辑,可以使用一些改进的变体:

          private bool isDGVRowDirty(DataGridView dgv, int idxrow)
      {
          if (idxrow < 0) return false;
          DataGridViewRow dgvRow = dgv.Rows[idxrow];
          DataRowView rowview = (DataRowView)dgvRow.DataBoundItem;
          DataRow row = rowview.Row;
          if (row.RowState == DataRowState.Unchanged)
              return false;
          if (row.RowState != DataRowState.Added || row.RowState == DataRowState.Modified)
          {
              return true;
          }
      
          for (int idxCol = 0; idxCol < dgv.Columns.Count - 1; idxCol++)
              if (dgv[idxCol, idxrow].FormattedValue.ToString() != dgv[idxCol, idxrow].Value.ToString()) return true;
      
          return false;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-14
        • 1970-01-01
        • 2013-06-10
        • 2011-01-08
        • 2014-09-15
        • 1970-01-01
        相关资源
        最近更新 更多