【问题标题】:What event catches a change of value in a combobox in a DataGridViewCell?什么事件会捕获 DataGridViewCell 中组合框中的值变化?
【发布时间】:2011-04-13 17:09:27
【问题描述】:

我想在 ComboBox 中的 DataGridView 单元格中的值发生更改时处理该事件。

CellValueChanged 事件,但直到我单击DataGridView 内的其他位置时才会触发。

一个简单的ComboBox SelectedValueChanged 在选择新值后会立即触发。

如何向单元格内的组合框添加侦听器?

【问题讨论】:

    标签: c# .net datagridview combobox event-handling


    【解决方案1】:

    上面的答案让我在报春花的道路上走了一段时间。它不起作用,因为它会导致多个事件触发并且只是不断添加事件。问题是上面捕获了 DataGridViewEditingControlShowingEvent 并且它没有捕获更改的值。因此,它会在您每次聚焦时触发,然后离开组合框,无论它是否已更改。

    关于CurrentCellDirtyStateChanged 的最后一个答案是正确的方法。我希望这可以帮助人们避免陷入困境。

    这里有一些代码:

    // Add the events to listen for
    dataGridView1.CellValueChanged += new DataGridViewCellEventHandler(dataGridView1_CellValueChanged);
    dataGridView1.CurrentCellDirtyStateChanged += new EventHandler(dataGridView1_CurrentCellDirtyStateChanged);
    
    
    
    // This event handler manually raises the CellValueChanged event 
    // by calling the CommitEdit method. 
    void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
    {
        if (dataGridView1.IsCurrentCellDirty)
        {
            // This fires the cell value changed handler below
            dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
        }
    }
    
    private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
    {
        // My combobox column is the second one so I hard coded a 1, flavor to taste
        DataGridViewComboBoxCell cb = (DataGridViewComboBoxCell)dataGridView1.Rows[e.RowIndex].Cells[1];
        if (cb.Value != null)
        {
             // do stuff
             dataGridView1.Invalidate();
        }
    }
    

    【讨论】:

    • 这对我帮助很大,正是我想要的。谢谢
    • 谢谢。我见过很多使用 EditedControlShowing 方法的示例,但由于可能是递归事件,我什至最终导致 .NET 崩溃。
    • @Severun Hai。我是 C# 的新手。我应该把事件放在哪里听?这部分我不是很懂。
    • 伙计们 - 注意这个答案 - 实际上告诉你在底部看到一个答案:) 节省你的时间:))))))
    • 您好,我试过这个方法,但是当我只更改了 1 个组合框单元时它会触发多次。
    【解决方案2】:

    您还可以处理CurrentCellDirtyStateChanged 事件,该事件在值更改时被调用,即使它没有被提交。要获取列表中的选定值,您可以执行以下操作:

    var newValue = dataGridView.CurrentCell.EditedFormattedValue;
    

    【讨论】:

    • 惊人的答案!它救了我!在我的情况下,还需要额外的检查:选择时发生两个事件,当进入新单元格时,旧的事件再次引发相同的事件:但通过检查 Combo 的 .Focused 属性很容易找到正确的事件。非常感谢!!!
    【解决方案3】:

    这是代码,它将触发 dataGridView 中组合框中的选择事件:

    public Form1()
    {
        InitializeComponent();
    
        DataGridViewComboBoxColumn cmbcolumn = new DataGridViewComboBoxColumn();
        cmbcolumn.Name = "cmbColumn";
        cmbcolumn.HeaderText = "combobox column";
        cmbcolumn.Items.AddRange(new string[] { "aa", "ac", "aacc" });
        dataGridView1.Columns.Add(cmbcolumn);
        dataGridView1.EditingControlShowing += new DataGridViewEditingControlShowingEventHandler(dataGridView1_EditingControlShowing);
    }
    
    private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
    {
        ComboBox combo = e.Control as ComboBox;
        if (combo != null)
        {
            combo.SelectedIndexChanged -= new EventHandler(ComboBox_SelectedIndexChanged);
            combo.SelectedIndexChanged += new EventHandler(ComboBox_SelectedIndexChanged);
        }
    }
    
    private void ComboBox_SelectedIndexChanged(object sender, EventArgs e)
    {
        ComboBox cb = (ComboBox)sender;
        string item = cb.Text;
        if (item != null)
            MessageBox.Show(item);
    }
    

    【讨论】:

    • 它可以工作但是正如@Severun 所说,它引发了太多事件。它工作了一段时间,但在某些情况下失败并引发InvalidOperationException: Operation is not valid because it results in a reentrant call to the SetCurrentAddressCore function 类型的致命错误。我使用了@Severun 的解决方案,现在一切正常
    • 感谢@MitjaBonca 的解决方案,但是如果我在 datagridview 中有两个组合框列怎么办。
    【解决方案4】:

    我已经实现了另一个解决方案,它似乎比上面的 Mitja Bonca 响应更快(例如更快和更少的点击)。虽然有时组合框会很快关闭。这使用了 CurrentCellDirtyStateChanged 和 CellMouseDown 回调

    private void myGrid_CurrentCellDirtyStateChanged(object sender, EventArgs e)
    {
        if (myGrid.CurrentCell is DataGridViewComboBoxCell)
        {
            myGrid.CommitEdit(DataGridViewDataErrorContexts.Commit);
            myGrid.EndEdit();
        }
    }
    
    private void myGrid_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
    {
        if (myGrid.Rows[e.RowIndex].Cells[e.ColumnIndex] is DataGridViewComboBoxCell)
        {
            myGrid.CurrentCell = myGrid.Rows[e.RowIndex].Cells[e.ColumnIndex];
            myGrid.BeginEdit(true);
            ((ComboBox)myGrid.EditingControl).DroppedDown = true; // Tell combobox to expand
        }
    }
    

    【讨论】:

      【解决方案5】:
      ComboBox cmbBox = (ComboBox)sender;                
      MessageBox.Show(cmbBox.SelectedValue.ToString());
      

      【讨论】:

      • @Sumett 这可能行得通,但是代码应该放置哪个事件?许多事件处理程序会更改 Sender 和 EventArgs 是什么,或者您可以将 EventArgs 转换为什么。没有上下文,对不起,这个答案毫无用处。为什么不提供活动...?如果没有上下文,建议任何人不要在这个答案上浪费时间。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-15
      • 1970-01-01
      • 1970-01-01
      • 2014-07-15
      • 1970-01-01
      • 2021-12-06
      相关资源
      最近更新 更多