ComboBoxCell Not Displaying Correctly - vb.net

I have a DataGridView, which has a ComboBoxColumn. This column is binded to a DataTable:
With dtYesOrNo
.Rows.Clear()
.Columns.Clear()
.Columns.Add("Description")
.Columns.Add("Code")
Dim statusRow = dtYesOrNo.NewRow
statusRow("Description") = ""
statusRow("Code") = 101
dtYesOrNo.Rows.Add(statusRow)
statusRow = dtYesOrNo.NewRow
statusRow("Description") = "Yes"
statusRow("Code") = 102
dtYesOrNo.Rows.Add(statusRow)
statusRow = dtYesOrNo.NewRow
statusRow("Description") = "No"
statusRow("Code") = 103
dtYesOrNo.Rows.Add(statusRow)
End With
Then I set DisplayMember to "Description", and ValueMember to "Code".
Dim colUECStatus As New DataGridViewComboBoxColumn
With colUECStatus
.DataSource = dtYesOrNo
.DataPropertyName = "StatusChk"
.Name = "StatusChk"
.DisplayMember = "Description"
.ValueMember = "Code"
'Combobox Formatting
.HeaderText = "Status"
.DisplayStyle = DataGridViewComboBoxDisplayStyle.ComboBox
.FlatStyle = FlatStyle.Flat
.DefaultCellStyle.BackColor = Color.FromArgb(255, 255, 192)
UECgrid.Columns.Insert(0, colUECStatus)
End With
But my problem is that when I actually load the form, it is giving me an exception for not having a valid value in my combox. For example, if the selection is "", the combo box would display 101, instead of "".
And here's the code where I load my grid (Note: please ignore the grid names -- UECgrid and dgvUEC1 are the same grid):
Dim row = 0
For Each checklist In USEFileChecklistUSChecklist.GetGeneralChecklist
objEFile.dgvUEC1.Rows(row).Cells("StatusChk").Value = checklist.statusCode
row += 1
Next

Related

System.InvalidOperationException when try to add new row on DataGridView

I've added some columns to a DataGridView using DataGridViewComboBoxColumn and DataGridViewColumn
Public Function a(ByVal wellName As String) As DataGridView
' Grid creation
Dim grid As DataGridView = New DataGridView With {
.Width = 1250,
.DataSource = New DataTable(),
.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
}
' Filling operations
grid.Columns.Add(New DataGridViewColumn With {
.HeaderText = "ID",
.Name = "ID",
.CellTemplate = New DataGridViewTextBoxCell()
})
Dim literatureDGVCB = New DataGridViewComboBoxCell() 'We don't know the lithology
literatureDGVCB.Style.BackColor = Color.LightGray
literatureDGVCB.FlatStyle = FlatStyle.Flat
grid.Columns.Add(New DataGridViewComboBoxColumn With {
.HeaderText = "Literature",
.Name = "literature",
.CellTemplate = literatureDGVCB,
.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing,
.[ReadOnly] = True
})
[ . . . ]
Return grid
End Function
Now, when i try to call
grid.Rows.Add( something )
i obtain a System.InvalidOperationException: "Cannot add rows programmatically to the DataGridView row collection if associated with control data." (or something like that: I'm translating).
How can I solve it?
As suggested by Ahmed Abdelhameed, removing the line DataSource = New DataTable(), the problem is solved.

How to fill a DataGridViewComboBoxColumn?

Sorry if this is something that should be obvious, but this is my first project using VB.NET, and some things are still beyond me.
I'm trying to setup a combobox inside a DataGridView but I keep getting
System.ArgumentException: DatagridviewComboBoxCell value not valid
I've been googling this for 2 hours now and to me it seems I'm setting up thing correctly, but probably something is amiss.
Dim imageCol As DataGridViewImageColumn
Dim checkCol As DataGridViewCheckBoxColumn
Dim col As DataGridViewColumn
Dim comboCol As DataGridViewComboBoxColumn
Dim ds As DataSet
Dim som As New SomStructure
Dim somministrazioni() As SomStructure = {}
With dgvListaAttivita
.Columns.Clear()
.AutoGenerateColumns = False
.ReadOnly = False
.EditMode = DataGridViewEditMode.EditOnEnter
.CausesValidation = False
somministrazioni.Clear
ds = getSomministrazioni(codevalue, Today())
If ds IsNot Nothing Then
For Each row As DataRow In ds.Tables(0).Rows
som.idOspite = row(0)
som.nomeOspite = row(1)
som.descrizioneSomministrazione = row(2)
som.idOperatore = row(3)
som.nomeOperatore = row(4)
som.preparata = False
somministrazioni.Add(som)
Next
End If
.DataSource = somministrazioni
imageCol = New DataGridViewImageColumn
imageCol.Width = 25
imageCol.ImageLayout = DataGridViewImageCellLayout.Normal
imageCol.Description = "delete"
imageCol.Image = My.Resources.note
.Columns.Add(imageCol)
col = New DataGridViewColumn
col.DataPropertyName = "descrizioneSomministrazione"
col.HeaderText = "Somministrazione"
col.ValueType = GetType(String)
col.CellTemplate = New DataGridViewTextBoxCell
col.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
col.ReadOnly = True
.Columns.Add(col)
comboCol = New DataGridViewComboBoxColumn
Dim dt As DataTable = dsOperatori.Tables(0)
comboCol.DataSource = dt
comboCol.DisplayMember = "display"
comboCol.ValueMember = "idoperatore"
comboCol.DataPropertyName = "idOperatore"
comboCol.HeaderText = "Operatore"
comboCol.ValueType = GetType(Integer)
comboCol.CellTemplate = New DataGridViewComboBoxCell
comboCol.Width = 150
.Columns.Add(comboCol)
checkCol = New DataGridViewCheckBoxColumn
checkCol.DataPropertyName = "preparata"
checkCol.HeaderText = "P."
checkCol.ValueType = GetType(Boolean)
checkCol.CellTemplate = New DataGridViewCheckBoxCell
checkCol.Width = 20
.Columns.Add(checkCol)
End With
As I understand it it should be like this:
comboCol.DataSource = dt
comboCol.DisplayMember = "display"
comboCol.ValueMember = "idoperatore"
specifies the datasource and key/display values of the comboboxes in the column
comboCol.DataPropertyName = "idOperatore"
Is the name of the column linked to both the DataSource of the DataGridView and the ValueMember of the ComboBox, and that should display different selections on different rows.
If I remove the DataPropertyName from the code I don't get the error anymore, but I also get empty comboboxes.
Try commenting out the template line:
comboCol = New DataGridViewComboBoxColumn
Dim dt As DataTable = dsOperatori.Tables(0)
comboCol.DataSource = dt
comboCol.DisplayMember = "display"
comboCol.ValueMember = "idoperatore"
comboCol.DataPropertyName = "idOperatore"
comboCol.HeaderText = "Operatore"
comboCol.ValueType = GetType(Integer)
'comboCol.CellTemplate = New DataGridViewComboBoxCell
comboCol.Width = 150
.Columns.Add(comboCol)

DataGridView Yes No ComboBox Column

I have what on the face of it seems a pretty simple requirement, I need an unbound combobox column to hold an option list of 'Yes' and 'No'. In combobox parlance Yes and No are the DisplayMembers corresponding to ValueMembers 1 and 0 respectively which in turn are the values held in the field of the database table. I use bound combobox columns in the application extensively and am very familiar with building them, but can't for the hell of me work out how to incorporate this simple list functionality in the datagridview application. Could somebody please put me out of my misery with some sample code.
Thanks for your feedback Plutonix. The DGV is bound to an underlying table. Hopefully, the following code should give you some idea of what I am attempting to acheive. The code specifically relevant to this post is in the call to PopulateUnboundComboBox(comboBoxCol, {"Yes", "No"}).
Private Sub GetData()
Const procName As String = "GetData()"
Dim myValue As String = ""
Dim myDataSource As Integer = 0
Try
'First clear the existing grid
With Me.uxGrid
If .ColumnCount > 0 Then
'clear the grid
ClearGrid(Me.uxGrid)
End If
End With
_Logger.SendLog(Me.Name & "." & procName & " - Fetching device data.", NLog.LogLevel.Trace)
'Get the data from the database
If Not _dataSourceID = 0 Then
_sqlStatement = "SELECT ID, TEXT, CATEGORY, MOUNTING, DATASOURCEID, TANALYSIS" & _
" FROM P_TBL_DEVICE WHERE DATASOURCEID = " & _dataSourceID
_criteria = "WHERE DATASOURCEID = " & _dataSourceID
Else
_sqlStatement = ""
_criteria = ""
End If
_myDeviceMngr = New DeviceManager(_currentDB, _userName, _myPwd)
'Now get the latest data
_myDataSet = _myDeviceMngr.GetData(_sqlStatement)
_Logger.SendLog(Me.Name & "." & procName & " - Device data fetch completed.", NLog.LogLevel.Trace)
'Update the display
Call BuildGrid(_myDataSet, uxGrid)
Catch ex As Exception
Beep()
MsgBox(ex.Message, MsgBoxStyle.Exclamation, System.Windows.Forms.Application.ProductName)
_Logger.SendLog(ex.Message & ". Thrown in module " & Me.Name.ToString & "." & procName, NLog.LogLevel.Error, ex)
Finally
Call System.GC.Collect()
End Try
End Sub
Private Sub BuildGrid(ByVal myDataSet As DataSet, ByVal myGrid As DataGridView)
Dim myTable As New System.Data.DataTable
Dim myColCount As Integer
Dim comboBoxCol As DataGridViewComboBoxColumn
Dim readOnlyCellStyle As New DataGridViewCellStyle
Dim textBoxCol As DataGridViewTextBoxColumn
Dim gridObject As Object = Nothing
Const procName As String = "BuildGrid"
readOnlyCellStyle.ForeColor = Color.Gray
Try
_Logger.SendLog(Me.Name & "." & procName & " - Building device data grid.", NLog.LogLevel.Trace, Nothing)
myTable = myDataSet.Tables(0)
With myGrid
'Now add the columns to the grid
Dim column As System.Data.DataColumn
For Each column In myDataSet.Tables(0).Columns
'We dont want to include the changedon and changedby fields in the grid build
If column.ColumnName.IndexOf("CHANGED") = -1 Then
Select Case column.ColumnName
Case "DATASOURCEID"
gridObject = New Object
comboBoxCol = New DataGridViewComboBoxColumn
'First create the comboboxcolumn for the column
'Populate combobox
PopulateScadaSourceComboBoxCol(comboBoxCol)
comboBoxCol.DataPropertyName = "DATASOURCEID"
comboBoxCol.HeaderText = "SCADA SOURCE"
comboBoxCol.AutoSizeMode = DataGridViewAutoSizeColumnsMode.AllCells
comboBoxCol.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing
gridObject = comboBoxCol
Case "TEXT"
textBoxCol = New DataGridViewTextBoxColumn
gridObject = textBoxCol
'Now add the columns to the grid
gridObject.DataPropertyName = column.ColumnName.ToString
gridObject.HeaderText = column.ColumnName.Replace("TEXT", "DEVICE")
gridObject.name = column.ColumnName.Replace("TEXT", "DEVICE")
gridObject.AutoSizeMode = DataGridViewAutoSizeColumnsMode.AllCells
Case "CATEGORY"
textBoxCol = New DataGridViewTextBoxColumn
gridObject = textBoxCol
'Now add the columns to the grid
gridObject.DataPropertyName = column.ColumnName.ToString
gridObject.HeaderText = "CATEGORY"
gridObject.name = "CATEGORY"
gridObject.AutoSizeMode = DataGridViewAutoSizeColumnsMode.AllCells
Case "MOUNTING"
textBoxCol = New DataGridViewTextBoxColumn
gridObject = textBoxCol
'Now add the columns to the grid
gridObject.DataPropertyName = column.ColumnName.ToString
gridObject.HeaderText = "MOUNTING"
gridObject.name = "MOUNTING"
gridObject.AutoSizeMode = DataGridViewAutoSizeColumnsMode.AllCells
Case "TANALYSIS"
comboBoxCol = New DataGridViewComboBoxColumn
'First create the comboboxcolumn for the column
'Populate combobox
PopulateUnboundComboBox(comboBoxCol, {"Yes", "No"})
comboBoxCol.DataPropertyName = "TANALYSIS"
comboBoxCol.HeaderText = "TELECONTROL ANALYSIS"
comboBoxCol.AutoSizeMode = DataGridViewAutoSizeColumnsMode.AllCells
comboBoxCol.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing
gridObject = comboBoxCol
Case Else
textBoxCol = New DataGridViewTextBoxColumn
gridObject = textBoxCol
'Now add the columns to the grid
gridObject.DataPropertyName = column.ColumnName.ToString
gridObject.HeaderText = "ID"
gridObject.name = "ID"
gridObject.AutoSizeMode = DataGridViewAutoSizeColumnsMode.AllCells
End Select
'Now add the textbox columns to the grid
'gridObject.DataPropertyName = column.ColumnName.ToString
'gridObject.AutoSizeMode = DataGridViewAutoSizeColumnsMode.AllCells
.Columns.Add(gridObject)
End If
Next
'Set grid default styles/values
.Font = New System.Drawing.Font("Arial", 10, FontStyle.Regular)
.AllowUserToResizeColumns = True
.AllowUserToResizeRows = True
.AllowUserToAddRows = True
.ReadOnly = True
.AutoResizeRows()
.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText
'Now bind the datatable to the DGV datasource property
.DataSource = myTable
End With
_Logger.SendLog(Me.Name & "." & procName & " - Building of device data grid has been completed.", NLog.LogLevel.Trace, Nothing)
Catch ex As Exception
Throw
Finally
textBoxCol = Nothing
comboBoxCol = Nothing
readOnlyCellStyle = Nothing
GC.Collect()
End Try
End Sub
Private Sub PopulateUnboundComboBox(ByVal comboBoxCol As DataGridViewComboBoxColumn, byval valList() as string)
comboBoxCol.Name = "TANALYSIS"
comboBoxCol.DataSource = valList
comboBoxCol.ValueMember = ???
comboBoxCol.DisplayMember = ???
End Sub
EDITED//
Ok, I've made some progress and seem to have almost solved my issue. The one remaining bug is that the column in the DGV is displaying the 'ValueMember' (1 or 0) rather than the 'DisplayMember' (Yes or No). I've checked the valuemember and displaymember properties in the comboboxcolumn definition and and they appear to be set correctly. Here is the associated code:
Excerpt from original code posting listed above
...
Case "TANALYSIS"
gridObject = New Object
comboBoxCol = New DataGridViewComboBoxColumn
'First create the comboboxcolumn for the column
'Populate combobox
Dim item As New CBOItem
Dim itemList As New CBOItemList
item.ValueMember = 0
item.DisplayMember = "No"
itemList.Add(item)
item = New CBOItem
item.ValueMember = 1
item.DisplayMember = "Yes"
itemList.Add(item)
PopulateComboBox(comboBoxCol, itemList)
comboBoxCol.DataPropertyName = "TANALYSIS"
comboBoxCol.HeaderText = "TELECONTROL ANALYSIS"
comboBoxCol.AutoSizeMode = DataGridViewAutoSizeColumnsMode.AllCells
comboBoxCol.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing
gridObject = comboBoxCol
...
Private Sub PopulateComboBox(ByRef comboBoxCol As DataGridViewComboBoxColumn, ByVal itemList As CBOItemList)
Dim tbl As DataTable = New DataTable
Dim row As DataRow
tbl.Columns.Add("ValueMember")
tbl.Columns.Add("DisplayMember")
row = tbl.NewRow
row.Item("ValueMember") = itemList(0).ValueMember
row.Item("DisplayMember") = itemList(0).DisplayMember
tbl.Rows.Add(row)
row = tbl.NewRow
row.Item("ValueMember") = itemList(1).ValueMember
row.Item("DisplayMember") = itemList(1).DisplayMember
tbl.Rows.Add(row)
comboBoxCol.ValueMember = tbl.Columns("ValueMember").ToString
comboBoxCol.DisplayMember = tbl.Columns("DisplayMember").ToString
comboBoxCol.DataSource = tbl
End Sub
Kind Regards
Paul J.

how to databind a comboboxcolumn on a datagridview with databind

So i have a datagridview on my project , and this is the code of my datagridview
With DataGridView1
.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCellsExceptHeaders
.ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single
.CellBorderStyle = DataGridViewCellBorderStyle.Single
.GridColor = Color.Black
.SelectionMode = DataGridViewSelectionMode.FullRowSelect
.MultiSelect = False
.AllowUserToResizeColumns = False
.AllowUserToAddRows = False
.ReadOnly = True
.AutoGenerateColumns = False
Me.DataGridView1.Columns("cod_produto").Visible = True
Me.DataGridView1.Columns("nome_produto").Visible = True
Me.DataGridView1.Columns("descricao").Visible = True
Me.DataGridView1.Columns("qtd_existente").Visible = True
Me.DataGridView1.Columns("qtd_minima").Visible = True
Me.DataGridView1.Columns("precounitario_venda").Visible = True
Me.DataGridView1.Columns("nome_fornecedor").Visible = True
Me.DataGridView1.Columns("categoria_produto").Visible = True
end with
Dim listaproduto As List(Of Produto) = CAD.CAD_Listar.ObterProduto()
Me.BindingSource1.DataSource = listaproduto
DataGridView1.DataSource = BindingSource1
now i wanted to create another column containing a combobox wich i did here
Dim lstcategoria As List(Of CategoriaProduto) = CAD.CAD_Listar.ObterCategoria()
Dim comboboxColumn As New DataGridViewComboBoxColumn
With comboboxColumn
.DataSource = lstcategoria
.DisplayMember = "categoriaproduto"
.ValueMember = "cod_categoriaproduto"
End With
DataGridView1.Columns.Add(comboboxColumn)
but this is not working, it does not trow any exeption but the combobox just stays with no items.i know the list is working because if i create a normal combobox(not in a comboboxcolumn) the combobox fills with the values of the list. but for some reason when i try to do the same but in a comboboxcolumn it just does not fill. can someone help me on this? thanks

Displaying a checkbox in a databound DataGridView

I am unable to correctly populate a DataGridView checkbox column from a boolean column from a database.
First form_load code:
Me.DataGridView1.DataSource = Me.bindingSource1
GetData("SELECT myInt, myBool, myString " & _
"FROM " & myFavTable & " " & _
"WHERE (myInt > 100) ORDER BY myString")
formatGrid()
In GetData I fill myTable with data:
Me.dataAdapter.Fill(myTable)
Me.bindingSource1.DataSource = myTable
And finally I format grid the before showing.
I format it manually because loading is much faster than with automatic formatting.
With DataGridView1
.AllowUserToAddRows = False
.AllowDrop = False
.AllowUserToOrderColumns = False
.AllowUserToResizeRows = False
.SelectionMode = DataGridViewSelectionMode.FullRowSelect
.MultiSelect = False
.Dock = DockStyle.Fill
.EditMode = DataGridViewEditMode.EditProgrammatically
With .Columns(0)
.Name = "postN"
.HeaderText = "Postal"
.Width = 55
End With
With .Columns(1) 'here should be a checkbox
.Width = 20
End With
With .Columns(2)
.Name = "colCity"
.HeaderText = "City"
.Width = 180
End With
End With
But with this code, in my column that should show checkboxes the string value 0 is displayed when in database is FALSE.
How in this situation can I get checkboxes in the middle column instead of text?
I try with .Columns.Add... before and after binding but with no wanted results.
That way I can get checkboxes, but in the new column.
In design-time add the columns to the DataGridView and set the middle column as a CheckBoxColumn.
Then set:
With DataGridView1
.AutoGenerateColumns = False
Edit:
I see the problem now. You need to set the DataPropertyName to be the same as the column.
When you add columns to the DataGridView, in that dialog set the DataPropertyName to match the DataTable (myTable) column Names. That's the magic behind the mapping.
Here is the code:
DataTable dt = new DataTable();
dt.Columns.Add("TextBoxCol");
dt.Columns.Add("CheckBoxCol");
DataRow dr = dt.NewRow();
dr[0] = "Hello";
dr[1] = false;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr[0] = "World";
dr[1] = true;
dt.Rows.Add(dr);
dataGridView1.DataSource = dt;
I had the same problem.
I had a DataSet that it was filling with this SQL:
"SELECT nombre, CASE WHEN fecha IS NULL THEN 0 ELSE 1 END AS baja"
Assignment
dtgEmpleado.DataSource = ds.Tables(0)
With dtgEmpleado
.Columns(0).HeaderText = "Nombre"
.Columns(0).DataPropertyName = "nombre"
.Columns(0).Name = "nombre"
.Columns(0).Width = 100
.Columns(1).HeaderText = "Baja"
.Columns(1).DataPropertyName = "baja"
.Columns(1).Name = "baja"
.Columns(1).Width = 70
End With
I wanted that the column "Baja" it was displaying as a "Checkbox".
I could do it with:
AutoGenerateColumns = False
But an easier way, changing the SQL sentence:
"SELECT nombre, CAST(CASE WHEN fecha IS NULL THEN 0 ELSE 1 END AS BIT) AS baja"
Dim cell As DataGridViewCell = New DataGridViewCheckBoxCell()
With DataGridView1
With .Columns(1)
.CellTemplate = cell
End With
End With
EDIT:
This a suggestion, don't try to add columns at design-time in your DataGridView because you query itself it will generate a DataGridViewCheckBoxCell
GetData("SELECT myInt AS Id, myBool AS Bool, myString AS String " & _
"FROM " & myFavTable & " " & _
"WHERE (myInt > 100) ORDER BY myString")
Me.dataAdapter.Fill(myTable)
Me.bindingSource1.DataSource = myTable
DataGridView1.DataSource = bindingSource1;