0
votes

I'm trying to add an item into a combobox after it's bind with the database so the combobox can have something like this:

Combobox

< Select Option >
Value 1
Value 2
Value 3

Tried with the code below but i'm getting the error "Items collection cannot be modified when the DataSource property is set." It's doesn't allow me to add another item after the combo box is bind. How can add an extra item into the combo box with a binded combo box?

Public Overloads Sub SqLoadCombo2(ByVal comboBox As ComboBox, ByVal cnnStr As String, ByVal TextField As String, ByVal ValueField As String, ByVal sAdditionalText As String, ByVal sAdditionalValue As String, ByVal sTextSeperator As String, ByVal sAdditionalTextDirection As String)
    comboBox.Items.Clear()

    Dim sAddText() As String
    Dim sAddValue() As String
    Dim iAddSize As Integer
    Dim iCtr As Integer

    Dim conn As New SqlConnection("SERVER=192.168.168.200,1433;DATABASE=WBIS_Laos;UID=BISSKG;PWD=BISSKG;Asynchronous Processing=false;")

    Dim strSQL As String = cnnStr
    Dim da As New SqlDataAdapter(strSQL, conn)
    Dim ds As New DataSet
    da.Fill(ds, "Disk")

    With comboBox
        .DataSource = ds.Tables("Disk")
        .DisplayMember = TextField
        .ValueMember = ValueField
        .SelectedIndex = 0
    End With

    '==Retrieve Additional Text and Value==
    If sAdditionalText.ToString <> "" Then
        sAddText = sAdditionalText.Split(sTextSeperator)
        sAddValue = sAdditionalValue.Split(sTextSeperator)
        iAddSize = sAddText.Length
    Else
        ReDim sAddText(0)
        ReDim sAddValue(0)
        iAddSize = 0
    End If
    '**Retrieve Additional Text and Value**


    '==Push Additional text into combo based on the direction request==
    sAdditionalTextDirection = sAdditionalTextDirection.ToString.Trim.ToUpper

    If sAdditionalTextDirection <> "TOP" And sAdditionalTextDirection <> "BTM" Then
        sAdditionalTextDirection = "TOP"
    End If

    If sAdditionalTextDirection = "BTM" Then
        For iCtr = 0 To iAddSize - 1
            comboBox.Items.Add(sAddText(iCtr))
            comboBox.Items(comboBox.Items.Count - 1).Value = sAddValue(iCtr)
        Next
    Else
        For iCtr = iAddSize - 1 To 0 Step -1
            comboBox.Items.Insert(0, sAddText(iCtr))
            comboBox.Items(0).Value = sAddValue(iCtr)
        Next
    End If
End Sub
3

3 Answers

1
votes

Instead of binding the combobox to a dataAdapter just create your own DataTable from scratch - fill your table first with the field(s) you want to add to your list and then loop through your reader adding each item to the DataTable. After this you can bind your table to your combobox. Below an example as I use it

Dim sqlHardware As String = "SELECT * FROM Hardware ORDER BY HardwareType"
Dim dtHardware As New DataTable, drHardware As DataRow
dtHardware.Clear()
dtHardware.Columns.Add(New DataColumn("ID", GetType(String))) '1
dtHardware.Columns.Add(New DataColumn("HardwareType", GetType(String))) ' 2
Dim commandHardware As New SqlCommand(sqlHardware, ConnMVC)
If ConnMVC.State <> 1 Then ConnMVC.Open()
Dim readerHardware As SqlDataReader = commandHardware.ExecuteReader()
If readerHardware.HasRows Then
    drHardware = dtHardware.NewRow()
    drHardware(0) = "0"
    drHardware(1) = "Select Type"
    dtHardware.Rows.Add(drHardware)
    Do While readerHardware.Read
        drHardware = dtHardware.NewRow()
        drHardware(0) = readerHardware!ID
        drHardware(1) = readerHardware!HardwareType
        dtHardware.Rows.Add(drHardware)
    Loop
    cbSoortHardware.DataSource = dtHardware
    cbSoortHardware.DisplayMember = "SoortHardware"
    cbSoortHardware.ValueMember = "ID"
    cbSoortHardware.SelectedIndex = 0
End If
1
votes

I use a BindingSource Object which I connect to the Source List and then tye it to the ComboBox. All manipulations arer transferde to the source and refreshed to the combobox. Just below a simple Sample with a combobox and a button:

Public Class Form1
Dim CoupledOrder As New List(Of clsCoupledOrder)

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim cOrder As clsCoupledOrder
    cOrder = New clsCoupledOrder("1", "Sunday")

    CoupledOrder.Add(New clsCoupledOrder("1", "Sunday"))
    CoupledOrder.Add(New clsCoupledOrder("2", "Monday"))
    CoupledOrder.Add(New clsCoupledOrder("3", "Tuesday"))
    CoupledOrder.Add(New clsCoupledOrder("4", "Wednesday"))
    CoupledOrder.Add(New clsCoupledOrder("5", "Thursday"))
    CoupledOrder.Add(New clsCoupledOrder("6", "Friday"))
    CoupledOrder.Add(New clsCoupledOrder("7", "Saturday"))

    BindingSource1.DataSource = New BindingSource(CoupledOrder, Nothing)

    ComboBox1.DataSource = BindingSource1
    ComboBox1.DisplayMember = "Value"
    ComboBox1.ValueMember = "Description"

End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    Dim AddValue As clsCoupledOrder = New clsCoupledOrder("8", "ExtraDay")

    BindingSource1.List.Insert(0, AddValue)
End Sub

Private Sub BindingSource1_CurrentChanged(sender As Object, e As EventArgs) Handles BindingSource1.CurrentChanged

End Sub

End Class

Public Class clsCoupledOrder
Private StringDesc As String
Private GUID As String

Public Sub New(ByVal desc As String, ByVal value As String)

    Me.StringDesc = desc
    Me.GUID = value

End Sub


Public Property Description() As String
    Get
        Return StringDesc
    End Get
    Set(ByVal value As String)
        StringDesc = value

    End Set
End Property

Public Property Value() As String
    Get
        Return GUID
    End Get
    Set(ByVal value As String)
        GUID = value
    End Set
End Property

End Class

0
votes

the my solution is to add a new row in your table at the top.

after

da.Fill(ds, "Disk")

insert this code :

Dim dr As DataRow = ds.Tables("Disk").NewRow
dr(ValueField) = -1                    ' NB :use dr(0) in others situation see example 
dr(TextField) = "< Select Option >"    ' NB :use dr(1) in others situation see example 
ds.Tables("Disk").Rows.InsertAt(dr, 0) ' Insert the new row to datatable's top

that's all

example :

    Dim da As New SqlDataAdapter("Select id, Description FROM CelleEssiccazione", sConnessione)
    Dim ds As New DataSet
    da.Fill(ds, "Disk")

    Dim dr As DataRow = ds.Tables("Disk").NewRow
    dr("id") = 0                         ' or dr(0)
    dr("Description ") = "Seleziona..."  ' or dr(1)
    ds.Tables("Disk").Rows.InsertAt(dr, 0)

    MyComboBox.DataSource = ds.Tables("Disk")
    MyComboBox.DisplayMember = ds.Tables("Disk").Columns("Description").ToString
    MyComboBox.ValueMember = ds.Tables("Disk").Columns("id").ToString