【问题标题】:How do I make a DataGridView immediately commit edits?如何使 DataGridView 立即提交编辑?
【发布时间】:2023-03-09 18:09:01
【问题描述】:

我有一个主从布局,其中包含弹出菜单部分(详细信息)和包含行的 DataGridView 部分。

当 DataGridView 中的选定行发生更改时,弹出菜单状态会更新,并且当弹出菜单更改时,DGV 的选定行中的状态应该更新。

所有这些都有效除了当我更改弹出菜单的值时,DataGridView 中的行不会立即更新。我必须选择不同的行才能看到我的编辑。

我假设这是因为在选择更改之前尚未提交编辑。

我的问题是:如何使对弹出窗口的更改立即反映在 DataGridView 中?

我已经尝试在弹出菜单的 SelectionChangeCommitted 处理程序中调用 EndEdit(),但这没有效果。我对一种允许我创建 DataGridView 的技术感兴趣,该技术的行为就像一开始就没有撤消机制一样。理想情况下,该解决方案应该是通用的并且可以移植到其他项目中。

【问题讨论】:

    标签: c# datagridview master-detail undo


    【解决方案1】:

    看起来现有答案与BindingSource 配合得很好。在我的情况下,DataTable 直接用作DataSource,但由于某种原因它们不起作用。

    // Other answers didn't work in my setup...
    private DataGridView dgv;
    
    private Form1()
    {
       var table = new DataTable();
       // ... fill the table ...
       dgv.DataSource = table;
    }
    

    经过一番拉扯后,我在不添加 BindingSource 间接寻址的情况下完成了工作:

    // Add this event handler to the DataGridView
    private void dgv_CellEndEdit(object sender, DataGridViewCellEventArgs e)
    {
        dgv.BindingContext[dgv.DataSource].EndCurrentEdit();
    }
    
    private Form1()
    {
       dgv.CellEndEdit += dgv_CellEndEdit;
       // ...
    }
    

    【讨论】:

    • 这对我有用。我们每个单元格都被应用而不必点击另一行。
    【解决方案2】:

    以下方法可以使用

    _dataGrid.EndEdit()
    

    设置值后就可以了。

    【讨论】:

      【解决方案3】:

      这对我很有效:

      private void CurrentCellDirtyStateChanged(object sender, EventArgs e)
      {
          var dgw = (DataGridView) sender;
          dgw.CommitEdit(DataGridViewDataErrorContexts.Commit);
      }
      

      【讨论】:

        【解决方案4】:

        使用此扩展方法。它适用于所有列类型,而不仅仅是组合框:

                public static void ChangeEditModeToOnPropertyChanged(this DataGridView gv)
                {
                    gv.CurrentCellDirtyStateChanged += (sender, args) =>
                    {
                        gv.CommitEdit(DataGridViewDataErrorContexts.Commit);
                        if (gv.CurrentCell == null)
                            return;
                        if (gv.CurrentCell.EditType != typeof(DataGridViewTextBoxEditingControl))
                            return;
                        gv.BeginEdit(false);
                        var textBox = (TextBox)gv.EditingControl;
                        textBox.SelectionStart = textBox.Text.Length;
                    };
                }
        

        此方法会在更改完成后提交所有更改。

        当我们有一个文本列时,在输入一个字符后,它的值将提交到数据源,单元格的编辑模式将结束。

        因此,当前单元格应返回编辑模式,并将光标位置设置为文本末尾,以便用户继续输入文本提示。

        【讨论】:

          【解决方案5】:

          这就是发生的事情。答案在ComboBox 实例的属性中。我需要将他们的DataSourceUpdateModeOnValidation 更改为OnPropertyChanged。这是有道理的。 DataGridView 很可能显示了数据的当前状态。只是数据还没有被编辑,因为焦点没有离开ComboBox,验证输入。

          感谢大家的回复。

          【讨论】:

            【解决方案6】:

            调用DataGridView.EndEdit 方法。

            【讨论】:

            • 应该添加更多细节。我知道 EndEdit 会导致这种情况发生。为了知道何时调用它,我需要观察什么?
            • @MichaelBishop 您可能需要在调用 EndEdit 之前完全完成当前的消息发送。使用BeginInvoke(new Action(()=>dgv.EndEdit())。这是有效的,因为 BeginInvoke 使用 PostMessage 来发布 WinForms 消息泵用来实现 BeginInvoke 的 WM_USER 消息。
            • 谢谢。 BeginInvoke(new Action(()=>dgv.EndEd‌​it())) 是唯一对我有用的东西。
            • 即使使用 BeginInvoke(new Action(() => dataGridView1.EndEdit())) 也不起作用;
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-04-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多