I have a windows forms application using VB.NET that is designed to upgrade IIS web applications.
The application has a datagridview that shows the list of web apps to upgrade. One of the columns is a DataGridViewComboBoxColumn. This combobox has its DataSource property set to a datatable. I do not use a bindingsource for the combobox.
The idea is that the user selects one of the values from the combobox in the datagridview row and several other cells’ values in the same datagridview row are updated.
The EditingControlShowing event handler is set to set the combobox’s SelectedIndexChanged event.
Private Sub dgvWebApps_EditingControlShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) Handles dgvWebApps.EditingControlShowing
If dgvWebApps.CurrentCell.ColumnIndex = 5 Then
Dim comboBox As ComboBox = CType(e.Control, ComboBox)
If comboBox IsNot Nothing Then
RemoveHandler comboBox.SelectedIndexChanged, AddressOf ComboBox_Value_Changed
AddHandler comboBox.SelectedIndexChanged, AddressOf ComboBox_Value_Changed
e.CellStyle.BackColor = clrLightYellow
End If
End If
End Sub
The ComboBox_Value_Changed is the subroutine that updates the other cells’ values.
Private Sub ComboBox_Value_Changed(sender As Object, e As EventArgs)
dgvWebApps.CurrentRow.Cells(frmMain.cnstNewVersion).Value = GetNewVersion(sender.Text)
dgvWebApps.CurrentRow.Cells(frmMain.cnstSourcePath).Value = strSourcePath
dgvWebApps.CurrentRow.Cells(frmMain.cnstSourceMediaFileUpdated).Value = True
dgvWebApps.CurrentCell = dgvWebApps.CurrentRow.Cells(frmMain.cnstSourceMediaFile)
End Sub
Also have the datagridview’s CurrentCellDirtyStateChanged event handled to commit the current edit immediately as the datagridview’s EditMode property is set to EditOnEnter, as well as update a cell’s values in the current datagridview row.
Private Sub dgvWebApps_CurrentCellDirtyStateChanged(sender As Object, e As EventArgs) Handles dgvWebApps.CurrentCellDirtyStateChanged
If dgvWebApps.CurrentCell.ColumnIndex = 1 Then
dgvWebApps.CurrentRow.Cells(frmMain.cnstLocalPath).Value = Path.Combine(strWebsitePhysicalPath, dgvWebApps.CurrentCell.Value)
End If
If dgvWebApps.IsCurrentCellDirty Then
dgvWebApps.CommitEdit(DataGridViewDataErrorContexts.Commit)
End If
End Sub
This works fine generally. I can select different values from the comboboxes in the datagridview and the other cells update accordingly, all while moving to different cells.
The issue I’m experiencing is after the user changes the value for the combobox and then changes the focus on the form to something other than the datagridview and then clicks back onto one of the comboboxes. This is when the datagridview’s DataError event is triggered and I get handful of the same errors.
This is the error:
Error Message: Items collection cannot be modified when the DataSource property is set.
Error StackTrace: at System.Windows.Forms.ComboBox.CheckNoDataSource() at System.Windows.Forms.DataGridViewComboBoxCell.InitializeEditingControl(Int32 rowIndex, Object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle) at System.Windows.Forms.DataGridView.InitializeEditingControlValue(DataGridViewCellStyle& dataGridViewCellStyle, DataGridViewCell dataGridViewCell)
The error obviously implies that the combobox’s items collection is getting modified when the datasource property has been set. However, nowhere in the code is the comboboxes’ items collection getting added, removed, or cleared.
If I continue through all the errors, or just not have any messages pop up during the datagrid's DataError event, everything seems to happen as it should. I can continue selecting values from the comboboxes, etc. But, if I change the focus again and come back to the combobox, the errors occur again.
From what I can tell, it’s the value changes of the other cells during the ComboBox_Value_Changed subroutine that is causing the error. Removing those makes the errors go away.
Now, this error doesn’t happen either if I use the SelectionChangeCommitted event instead of the SelectedIndexChanged event for the combobox to call the ComboBox_Value_Changed subroutine. This was the event I was initially using but it wasn't being consistently raised with certain user interactions on the form. Which is why I switched to the SelectedIndexChanged event after some research into those behaviors.
I'm not sure why the combobox's items collection is being modified during these circumstances. As stated before, I can just handle the datagridview's DataError event to not generate any messages and everything seems to work as expected. I would just like to know what's going here if at all possible. I don't like to suppress errors when they occur if I don't have to.