You have a pseudo-table class and a pseudo-row class. The row is somewhat generic and has no strongly-typed fields. It follows the typical dictionary interface
Dim age As Object = person("Age") 'accessed via default property Item
vs
Dim age As Integer = person.Age 'an actual property typed as an Integer
What’s the pattern to use so that we can bind our pseudo table and its rows to a grid or combo box?
Dim rs As New clsResultSet(tblPeople)
Dim id As Object = rs(0)("Id") '913
Dim name As Object = rs(0)("Name") 'Ted
Dim age As Object = rs(0)("Age") '43
Dim occupation As Object = rs(0)("Occupation") 'cab driver
grd.DataSource = rs 'In grid I expect to see Name, Age, Occupation columns
cbo.DataSource = rs
cbo.DisplayMember = "Name" 'could we do this?
cbo.ValueMember = "Id" '...and this?
I read all about IList, IBindingList, BindingSource, etc., tried some things, and I’m still puzzling over how to get this right. Most examples I’ve found expect your record objects to be strongly typed (e.g. person.Age rather than person(“Age”)).
Here are some simple classes to start with:
Public Class clsResultSet 'Like a DataTable
Inherits List(Of clsRecord)
Private mdicFields As New Dictionary(Of String, Object)
Public Sub New(vdt As DataTable) 'Loaded from table
For Each bdc As DataColumn In vdt.Columns
Me.mdicFields.Add(bdc.ColumnName, bdc)
Next
For Each vdr As DataRow In vdt.Rows
Me.Add(New clsRecord(vdr, Me))
Next
End Sub
Public ReadOnly Property Fields As Dictionary(Of String, Object)
Get
Return Me.mdicFields
End Get
End Property
End Class
Public Class clsRecord 'Like a DataRow
Inherits Dictionary(Of String, Object)
Private mrs As clsResultSet
Protected Friend Sub New(vdr As DataRow, vrs As clsResultSet)
Me.mrs = vrs
For Each bPair As KeyValuePair(Of String, Object) In vrs.Fields
Me.Add(bPair.Key, vdr(bPair.Key))
Next
End Sub
End Class
This question, as asked, was answered. I reframed it since I didn’t get to the root of my problem.
As far as I know there is no way to directly bind to dictionary objects. Here’s a quick workaround for a combobox with a fixed DataSource. Create a new list with the desired properties using Select and anonymous objects (works with Visual Studio 2008 and newer):
I suppose you could use a similar approach to bind to a DataGridView, but I would recommend using a strongly-typed class instead (a Person class with properties Name, Age, etc.), unless it’s a read-
only DataGridView that won’t change.
Edit:
You might be interested in the Remarks section of the DataGridView.DataSource documentation. Basically the DataSource can be either an
IList,IListSource,IBindingListorIBindingListView. DataTable and DataSet classes implementIListSourceso it might be worth trying to implement this interface for your own class.