PDA

Click to See Complete Forum and Search --> : Combobox and adding values manually


BryanJ
Jun 17th, 2002, 08:53 PM
How do you add the Valuemembers manually.

I want to populate a combobox manually and not through databinding. With each Displaymember I add, I would like to add an associated reference value - like the itemdata value in VB6.

Is there any simple method of doing this.

Doorstep
Oct 10th, 2002, 04:38 PM
Microsoft has done away with the ItemData property and replaced it with ValueMember, which is completely useless unless you bind the combobox to a live datasource.

This is a unique solution to the same problem alot of people are experiencing but have no answer for, other than binding to a data source.

Seeing as the ComboBox.Tag property supports an Object, why not preload an array object with the primary key values and stick the whole thing in the combobox tag property? Works for me.

***** I hate Micro$oft some days...

x--------- snip here -----------x

'Declarations:

Imports System
Imports System.Data
Imports System.Data.SqlClient
Imports System.Data.OleDb
Imports Microsoft.VisualBasic


'Calling Convention:

LoadComboBoxItems (cboExistCond, "ExistingCond", "Condition", "ExistingCond_ID", "")


'Black-box sub that populates a combobox with records from a table:

Private Sub LoadComboBoxItems( _
ByVal cboComboBox As ComboBox, _
ByVal strTableName As String, _
ByVal strFieldName As String, _
ByVal strUniqueKeyField As String, _
ByVal strTableFilter As String _
)


Dim objConn As OleDbConnection
Dim objAdap As OleDbDataAdapter
Dim objDS As New DataSet()
Dim sSQL As String
Dim objTBL As DataTable
Dim iCnt As Integer
Dim strFieldContents As String

Dim sConnect As String = "Provider=Microsoft.JET.OLEDB.4.0;Data Source=c:\data\MyAccessDatabase.mdb"
Dim strTargetDS As String = "DS_" & strTableName

sSQL = "SELECT * FROM " & strTableName
If strTableFilter <> Nothing Then
sSQL = sSQL + " WHERE " & strTableFilter
End If

objConn = New OleDbConnection(sConnect)
objAdap = New OleDbDataAdapter(sSQL, objConn)

Try
objAdap.Fill(objDS, strTargetDS)
Catch eSql As Exception
MsgBox(eSql.ToString)
End Try

Dim myIntArray(0) As Double

For iCnt = 1 To objDS.Tables(strTargetDS).Rows.Count
strFieldContents = objDS.Tables(strTargetDS).Rows(iCnt - 1).Item(strFieldName)
ReDim Preserve myIntArray(iCnt)
myIntArray(iCnt) = objDS.Tables(strTargetDS).Rows(iCnt - 1).Item(strUniqueKeyField)
cboComboBox.Items.Add(strFieldContents)
Next

cboComboBox.Tag = myIntArray

End Sub


'The proof of the pudding...

Private Sub cboExistCond_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboExistCond.SelectedIndexChanged

MessageBox.Show("Selected Item Text: " & cboExistCond.SelectedItem & vbCrLf & _
"Index: " & cboExistCond.SelectedIndex & vbCrLf & _
"Primary Key: " & cboExistCond.Tag(cboExistCond.SelectedIndex + 1))

End Sub

x--------- snip here -----------x

Best regards,
George

Edneeis
Oct 10th, 2002, 04:51 PM
Actually you can use databinding with anything that implements IList or IListSource, even a class or collection class or things like an arraylist.


'make data to fill list
Dim MyList As New ArrayList()
MyList.Add(New GenericList("Jack Hammer", 1))
MyList.Add(New GenericList("Sledge Hammer", 2))
MyList.Add(New GenericList("Screwdriver", 3))
MyList.Add(New GenericList("Wrench", 4))

'bind list
ComboBox1.DataSource = MyList
ComboBox1.DisplayMember = "Display"
ComboBox1.ValueMember = "ID"

Public Class GenericList

Private _Display As String
Private _ID As Integer

Public Property Display() As String
Get
Return _Display
End Get
Set(ByVal Value As String)
_Display = Value
End Set
End Property

Public Property ID() As Integer
Get
Return _ID
End Get
Set(ByVal Value As Integer)
_ID = Value
End Set
End Property

Public Sub New()
MyBase.new()
End Sub

Public Sub New(ByVal display As String, ByVal id As Integer)
Me.Display = display
Me.ID = id
End Sub

End Class


Although you can store the whole object in the item so just reference that part of it that is the value from the SelectedItem property of the combo.

Edneeis
Oct 10th, 2002, 04:57 PM
Oh and one quick way to make a class bindable is just adding this:


Inplements System.ComponentModel.IListSource

Private ReadOnly Property ContainsListCollection() As Boolean Implements IListSource.ContainsListCollection
Get
Return False
End Get
End Property

Public Function GetList() As IList Implements IListSource.GetList
Dim al As New ArrayList()
al.Add(Me)
Return al
End Function



There are also some other interfaces that inherit from IList or IListSource that you can use that provide more features like IBindingList.

Doorstep
Oct 10th, 2002, 05:02 PM
I tried something similiar to that and couldn't get it to work, was getting some bs about not being able to bind ValueMember. Also was having problems properly declaring the public class. The main reason behind my post was to present a solution that was more intuitive for us VB6 folks. I also didn't want to rely on the VB6 compatibility library because who knows how long it will be supported.

I'm still learning Object-oriented programming techniques and I am very new to this. Thanks for posting just the same. I'll try your method tomorrow.

Cheers,
George

Doorstep
Oct 11th, 2002, 08:41 AM
Edneeis, I tried incoroprating your suggestion and can't figure out how to actually reference the values from the combobox (sigh).

Could you please post a combobox_change event for your example? TIA

P.S. Using your suggested method, it seems like one has to create a fair amount of code just to return something as simple as as reference to itemdata. But alas, I hate relying on a kludges to do something (which is why I'm working with .Net in the 1st place.)

Cheers,
George

Edneeis
Oct 11th, 2002, 10:13 AM
Sure no problem:

Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
Dim gl As GenericList = CType(ComboBox1.SelectedItem, GenericList)
MsgBox(gl.Display, , gl.ID)
End Sub

Doorstep
Oct 11th, 2002, 11:03 AM
Where were you two days ago?? :)
Thanks for the excellent example

BryanJ
Oct 11th, 2002, 01:09 PM
Ednis - Good job.

I agree where were you 4 months ago.

stingrae
Dec 7th, 2002, 11:28 PM
Edneesis:

you are a LEGEND!

Microsoft: WHY make our lives so difficult?

??

Athley
Dec 8th, 2002, 07:49 AM
A thing worth mentioning in this thread is the fact that Comboboxes, Listboxes and other objects of the kind do accept objects as listitems. Therefore there is no need for the itemdata and such anymore. You just make your own Item class and its done.

Public Class ListItem

Dim m_ItemData As String
Dim m_ItemDisplay As String

Sub New(ByVal Value As String, ByVal Data As String)
Me.m_ItemData = Data
Me.m_ItemDisplay = Value
End Sub

Overrides Function ToString() As String
Return ItemDisplay
End Function

Property ItemData()
Get
Return m_ItemData
End Get
Set(ByVal Value)
m_ItemData = Value
End Set
End Property

Property ItemDisplay()
Get
Return m_ItemDisplay
End Get
Set(ByVal Value)
m_ItemDisplay = Value
End Set
End Property

End Class
You are now able to add ListItems to the combobox instead. Something like this....

Combobox1.Items.Add(New ListItem("Test", "1"))
And to get it back you Cast it back to a listitem again.....

DirectCast(cboDiscrepancy.SelectedItem, ListItem).ItemData

stingrae
Dec 8th, 2002, 05:13 PM
Edneeis,

i implemented your example and it works really well the first time, but after use it the second time it doesn't.

by that i mean:
i fill it with data once, then
clear the object - items.clear (i also tried setting DataSource = Nothing)
then run the same function to fill the data.

on the second and subsequent runs, all that appears in my listbox is "MyApplicationName.GenericList".

are you able to help?

cheers

Edneeis
Dec 8th, 2002, 05:25 PM
I'll check it out but off the top of my head, you may need to reset the DisplayMember. Did you try that?

Edneeis
Dec 8th, 2002, 05:30 PM
Well I so far haven't been able to reproduce the problem, everything worked fine for me. Can you post your code and I'll try and help.

stingrae
Dec 8th, 2002, 05:38 PM
Thanks for your quick reply. As mentioned, when i run it the first time, sweet, then the second call, it's a little bizarre?

here are my functions:


Private Sub lstItemDescriptions_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lstItemDescriptions.SelectedIndexChanged
lstDates.DataSource = Nothing
Dim gl As GenericList = CType(lstItemDescriptions.SelectedItem, GenericList)
LoadItemDates(lstDates, gl.ID)
End Sub

Public Function LoadItemDates(ByVal objDates As Object, ByVal ItemID As Integer)
Dim strSQLStm As String = "SELECT * " & _
"FROM tbl_ItemDates " & _
"WHERE itd_Item = " & ItemID & " " & _
"ORDER BY itd_Start DESC"
Dim cmdDates As New OleDb.OleDbCommand(strSQLStm, gconDatabase)
Dim datDates As OleDb.OleDbDataReader
Dim mylist As New ArrayList()
Dim blnItemFound As Boolean = False

cmdDates.Connection = gconDatabase
datDates = cmdDates.ExecuteReader
Do Until datDates.Read = False
blnItemFound = True
mylist.Add(New GenericList(Format(datDates("itd_Start"), "ddd dd-MM-yyyy"), datDates("itd_ID")))
Loop
datDates.Close()
objDates.DataSource = mylist
If blnItemFound = True Then objDates.ValueMember = "Display"
End Function

Edneeis
Dec 8th, 2002, 07:37 PM
Try this:

Private Sub lstItemDescriptions_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lstItemDescriptions.SelectedIndexChanged
lstDates.DataSource = Nothing
Dim gl As GenericList = CType(lstItemDescriptions.SelectedItem, GenericList)
LoadItemDates(lstDates, gl.ID)
End Sub

Public Function LoadItemDates(ByVal objDates As Object, ByVal ItemID As Integer)
Dim strSQLStm As String = "SELECT * " & _
"FROM tbl_ItemDates " & _
"WHERE itd_Item = " & ItemID & " " & _
"ORDER BY itd_Start DESC"
Dim cmdDates As New OleDb.OleDbCommand(strSQLStm, gconDatabase)
Dim datDates As OleDb.OleDbDataReader
Dim mylist As New ArrayList()
Dim blnItemFound As Boolean = False

cmdDates.Connection = gconDatabase
datDates = cmdDates.ExecuteReader
Do Until datDates.Read = False
blnItemFound = True
mylist.Add(New GenericList(Format(datDates("itd_Start"), "ddd dd-MM-yyyy"), datDates("itd_ID")))
Loop
datDates.Close()
objDates.DataSource = mylist
objDates.DisplayMember = "Display"
objDates.ValueMember = "ID"
End Function

stingrae
Jan 23rd, 2003, 07:08 PM
Athley,

I've been using your method ever since, and it works fantastic! Just one query though. How do you step through each item in the combo box looking for the right ItemData? for example here's the VB6 version:

For i = 0 To cboData.ListCount - 1
If cboData.ItemData(i) = ID Then
cboData.ListIndex = i
Exit For
End If
Next i


thanks

stingrae
Jan 24th, 2003, 04:40 AM
figured it out! here it is for anybody who needs it:


Public Function SearchCombo(ByVal FullCombo As ComboBox, ByVal ItemData As String)
Dim i As Integer
For i = 0 To FullCombo.Items.Count - 1
If DirectCast(FullCombo.Items.Item(i), ListItem).ItemData = ItemData Then
FullCombo.SelectedItem = FullCombo.Items.Item(i)
Exit For
End If
Next i
End Function