Lets say I have a class teacher which inherits from a class person (hard to believe I know ;-)). And we want to bind a list of Iteachers (the interface) to a datagridview because that is the easiest way of getting things working for the datagridview. This will give a surprising (perhaps not) result.
First lets look at the Person class and IPerson interface.
Public Interface IPerson
Property Name() As String
Property FirstName() As String
End Interface
Public Class Person
Implements IPerson
Private _name As String
Private _firstname As String
Public Sub New()
End Sub
Public Sub New(ByVal Name As String, ByVal Firstname As String)
_name = Name
_firstname = Firstname
End Sub
Public Property Name() As String Implements IPerson.Name
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
End Set
End Property
Public Property FirstName() As String Implements IPerson.FirstName
Get
Return _firstname
End Get
Set(ByVal value As String)
_firstname = value
End Set
End Property
End Class
And then the Teacher class and ITeacher interface which inherits from IPerson.
Public Interface ITeacher
Inherits IPerson
Property ClassRoom() As String
End Interface
Public Class Teacher
Inherits Person
Private _classroom As String
Public Sub New()
End Sub
Public Sub New(ByVal name As String, ByVal FirstName As String, ByVal ClassRoom As String)
MyBase.New(Name, FirstName)
_classroom = ClassRoom
End Sub
Public Property ClassRoom() As String
Get
Return _classroom
End Get
Set(ByVal value As String)
_classroom = value
End Set
End Property
End Class
And then we bind it to the datagridview via a bindingsource. Like so
Public Class Form1
Dim _bs As BindingSource
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim _l As New List(Of ITeacher)
_l.Add(New Teacher("t1", "f1", "A"))
_l.Add(New Teacher("t2", "f2", "B"))
_l.Add(New Teacher("t3", "f3", "C"))
_l.Add(New Teacher("t4", "f4", "D"))
_l.Add(New Teacher("t5", "f5", "E"))
_l.Add(New Teacher("t6", "f6", "F"))
_l.Add(New Teacher("t7", "f7", "G"))
_bs = New BindingSource
_bs.DataSource = _l
Me.DataGridView1.DataSource = _bs.DataSource
End Sub
End Class
If we run this we will get this.
So where did the person data go?
And know watch even more closely and find the difference.
Public Class Form1
Dim _bs As BindingSource
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim _l As New List(Of Teacher)
_l.Add(New Teacher("t1", "f1", "A"))
_l.Add(New Teacher("t2", "f2", "B"))
_l.Add(New Teacher("t3", "f3", "C"))
_l.Add(New Teacher("t4", "f4", "D"))
_l.Add(New Teacher("t5", "f5", "E"))
_l.Add(New Teacher("t6", "f6", "F"))
_l.Add(New Teacher("t7", "f7", "G"))
_bs = New BindingSource
_bs.DataSource = _l
Me.DataGridView1.DataSource = _bs.DataSource
End Sub
End Class
And see the result.
Yes the fields are there. Why does this happen? Well reflection and a bug in the interface implementation. Reflection should pick up the properties from IPerson in ITeacher like it does for the class but it doesn’t so your ……. The only solution that works is either bind to teacher or (like in my case) make a private class that accepts an ITeacher and has all the properties needed).
and why in my case? Because I only pass interface between my different layers, never implmentations.
Something like this.
```vbnet Public Class LocalTeacher Implements ITeacher
Private _teacher As ITeacher
Public Sub New(ByVal Teacher As ITeacher)
_teacher = Teacher
End Sub
Public Property Name() As String Implements IPerson.Name
Get
Return _teacher.Name
End Get
Set(ByVal value As String)
_teacher.Name = value
End Set
End Property
Public Property FirstName() As String Implements IPerson.FirstName
Get
Return _teacher.FirstName
End Get
Set(ByVal value As String)
_teacher.FirstName = value
End Set
End Property
Public Property ClassRoom() As String Implements ITeacher.ClassRoom
Get
Return _teacher.ClassRoom
End Get
Set(ByVal value As String)
_teacher.ClassRoom = value
End Set
End Property
Public ReadOnly Property Teacher() As ITeacher
Get
Return _teacher
End Get
End Property
End Class``` And then this for the form.
```vbnet Public Class Form1 Dim _bs As BindingSource
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'normally I would get this from the DAL
Dim _l As New List(Of ITeacher)
_l.Add(New Teacher("t1", "f1", "A"))
_l.Add(New Teacher("t2", "f2", "B"))
_l.Add(New Teacher("t3", "f3", "C"))
_l.Add(New Teacher("t4", "f4", "D"))
_l.Add(New Teacher("t5", "f5", "E"))
_l.Add(New Teacher("t6", "f6", "F"))
_l.Add(New Teacher("t7", "f7", "G"))
'Then I have to do this to it
Dim _l2 As New List(Of LocalTeacher)
For Each T As ITeacher In _l
_l2.Add(New LocalTeacher(T))
Next
_bs = New BindingSource
_bs.DataSource = _l2
Me.DataGridView1.DataSource = _bs.DataSource
End Sub
End Class``` and then of course it’s a mess to save it again ;-). Call me nuts :crazy: and tell me I should just pass the objects. But trust me I won’t. I’ll keep the interfaces and live with this kind of thing.
Need help with VB.Net? Come and ask a question in our VB.Net Forum