Wednesday, November 28, 2012

ComboBoxColumn vs ComboBoxCell

This article is meant to show the drastic differences between DataGridViewComboBoxColumn and DataGridViewComboBoxCell that I have discovered so far. Once again I could not find anything in Google that would make even the slightest sense to me.



1. DataGridViewComboBoxColumn is NOT meant for data storage. Regardless of how many rows you may have in your Datagridview, DataGridViewComboBoxColumn is a SINGLE entity. If you have a hundred rows, every time you click into any cell of that column, your program displays THE SAME instance of the combobox. Consequently it remembers only ONE, latest selection.

- On the bright side you only have to create one of them for the whole Datagridview, for example:

Dim cmb As New DataGridViewComboBoxColumn
Dim dgbTypes As New BindingSource
dgbTypes.DataSource = allTypes.Tables(0) 'allTypes is a DataSet full of Types
cmb.DataSource = dgbTypes
cmb.ValueMember = "TYPE_ID"
cmb.DisplayMember = "TYPE_NAME"
cmb.HeaderText = "   TYPE   "
cmb.Name = "TYPE"
cmb.MaxDropDownItems = 8

- How can it be useful? If you don't want to create excessive amounts of data storage in your program and are using it to affect some other rows or calculations, then DataGridViewComboBoxColumn is the way to go.
- If you decide to use it you will also need some extra code to actually get it to work. In the following example I'm changing the value in another column according to the user selection:

'This code deletes system handler and creates a custom one for us to play with inside this instance only
Private Sub DataGridView1_EditingControlShowing(ByVal sender As Object, ByVal e As DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
        If DataGridView1.CurrentCell.ColumnIndex = 25 Then
            Dim selectedComboBox As ComboBox = DirectCast(e.Control, ComboBox)
            RemoveHandler selectedComboBox.SelectionChangeCommitted, AddressOf selectedComboBox_SelectionChangeCommitted
            AddHandler selectedComboBox.SelectionChangeCommitted, AddressOf selectedComboBox_SelectionChangeCommitted
        End If
End Sub

'This is the actual custom combobox selection commitment handler
Private Sub selectedComboBox_SelectionChangeCommitted(ByVal sender As Object, ByVal e As EventArgs)
        Dim selectedCombobox As ComboBox = DirectCast(sender, ComboBox)
        If selectedCombobox.SelectedItem IsNot Nothing Then
            DataGridView1("TYPE_ID", DataGridView1.CurrentCell.RowIndex).Value = selectedCombobox.SelectedValue
        End If
End Sub


2. DataGridViewComboBoxCell is a cell MASK.
- You should ALREADY have an existing cell to apply it to.
- You have to apply it to each cell separately.
In the following example I create a DataGridViewComboBoxCell, bind it to some data and my ValueMember HAS to coincide with whatever data I have in the cells that I'm masking (integer to integer, string to string, etc.):

For i As Integer = 0 To DataGridView1.Rows.Count + 1
            'This code dynamically makes TYPE column into column full of comboboxes
            Dim dgvCell As New DataGridViewComboBoxCell
            Dim dgbTypes As New BindingSource
            dgbTypes.DataSource = frmAuction.allTypes.Tables(0)
            dgvCell.DataSource = dgbTypes
            dgvCell.ValueMember = "TYPE_ID"
            dgvCell.DisplayMember = "TYPE_NAME"
            DataGridView1.Rows(i).Cells("TYPE") = dgvCell
 Next
- Fancy stuff, all my ugly integer TYPE_ID values suddenly became pretty combo boxes with names in them.

- It's dynamic and goes through your whole datagridview, which can be a lot.

No comments: