Reputation: 49619
I have a windows forms DataGridView
that contains some DataGridViewComboBoxCell
s that are bound to a source collection using DataSource
, DisplayMember
and ValueMember
properties. Currently the the combobox cell commits the changes (i.e. DataGridView.CellValueChanged
is raised) only after I click on another cell and the combobox cell loses focus.
How would I ideally commit the change directly after a new value was selected in the combobox.
Upvotes: 3
Views: 1725
Reputation: 489
A better way to achieve this that I am using successfully rather than subclassing or the somewhat inelegant binding source method above, is the following (sorry it's VB but if you can't translate from VB to C# you have bigger problems :)
Private _currentCombo As ComboBox
Private Sub grdMain_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles grdMain.EditingControlShowing
If TypeOf e.Control Is ComboBox Then
_currentCombo = CType(e.Control, ComboBox)
AddHandler _currentCombo.SelectedIndexChanged, AddressOf SelectionChangedHandler
End If
End Sub
Private Sub grdMain_CellEndEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles grdMain.CellEndEdit
If Not _currentCombo Is Nothing Then
RemoveHandler _currentCombo.SelectedIndexChanged, AddressOf SelectionChangedHandler
_currentCombo = Nothing
End If
End Sub
Private Sub SelectionChangedHandler(ByVal sender As Object, ByVal e As System.EventArgs)
Dim myCombo As ComboBox = CType(sender, ComboBox)
Dim newInd As Integer = myCombo.SelectedIndex
//do whatever you want with the new value
grdMain.NotifyCurrentCellDirty(True)
grdMain.CommitEdit(DataGridViewDataErrorContexts.Commit)
End Sub
That's it.
Upvotes: 0
Reputation: 56650
I tried using Bradley's suggestion, but it was sensitive to when you attached the cell template. It seemed like I couldn't allow the design view to wire up the column, I had to do it myself.
Instead, I used the binding source's PositionChanged event, and triggered updates from that. It's a little bit odd, because the control is still in edit mode, and the databound object doesn't get the selected value yet. I just updated the bound object myself.
private void bindingSource_PositionChanged(object sender, EventArgs e)
{
(MyBoundType)bindingSource.Current.MyBoundProperty =
((MyChoiceType)comboBindingSource.Current).MyChoiceProperty;
}
Upvotes: 0
Reputation: 13601
This behaviour is written into the implementation of the DataGridViewComboBoxEditingControl
. Thankfully, it can be overridden. First, you must create a subclass of the aforementioned editing control, overriding the OnSelectedIndexChanged
method:
protected override void OnSelectedIndexChanged(EventArgs e) {
base.OnSelectedIndexChanged(e);
EditingControlValueChanged = true;
EditingControlDataGridView.NotifyCurrentCellDirty(true);
EditingControlDataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
This will ensure that the DataGridView
is properly notified of the change in item selection in the combo box when it takes place.
You then need to subclass DataGridViewComboBoxCell
and override the EditType
property to return the editing control subclass from above (e.g. return typeof(MyEditingControl);
). This will ensure that the correct editing control is created when the cell goes into edit mode.
Finally, you can set the CellTemplate
property of your DataGridViewComboBoxColumn
to an instance of the cell subclass (e.g. myDataGridViewColumn.CellTemplate = new MyCell();
). This will ensure that the correct type of cell is used for each row in the grid.
Upvotes: 1