Published on

DataBinding and Pointers, or "Why is my DataBinding not working?"

Authors

Let's say you have the following class:

Public Class Person
Private _name As String

Public Event NameChanged As EventHandler

Public Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
OnNameChanged(EventArgs.Empty)
End Set
End Property

Protected Sub OnNameChanged(ByVal e As EventArgs)
RaiseEvent NameChanged(Me, e)
End Sub
End Class


We've set up the [Property]Changed events so that DataBinding will work correctly. Now, let's assume you want to bind the name property over to the text property of your TextBox control. We'll go the simple data binding route here for simplicity.

Public Class Form1
Private txtName As New TextBox
Private _person As New Person

Public Sub New()
' This call is required by the Windows Form Designer.
InitializeComponent()

' Add any initialization after the InitializeComponent() call.

_person.Name = "cool"
End Sub

Private Sub Form_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Click
_person.Name = "clicked"
End Sub
End Class


There! Now the txtName will display "clicked" whenever you click on the form. Magic! Now, let's change that Click event like so to see what happens:

Private Sub Form_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Click
Dim newPerson As New Person
newPerson.Name = "new person"
_person = newPerson
End Sub


Why would I ever want to do is this way? Well, let's say you're remoting somewhere to get your data and your background thread returns a fully populated object. The easiest thing to do is to just point to the new object... except that it doesn't work.

All we did was change our instance over, but the textbox never changed. Why not? Because of REFERENCES, POINTERS, and MEMORY ADDRESSES! That's why! Check this out:

Private Sub Form_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Click
Dim newPerson As New Person
newPerson.Name = "new person"

Debug.WriteLine("Are references equal? " & Object.ReferenceEquals(txtName.DataBindings("Text").DataSource, _person))
_person = newPerson
Debug.WriteLine("Are references equal? " & Object.ReferenceEquals(txtName.DataBindings("Text").DataSource, _person))
End Sub


Whoa! The first Debug.Writeline will give you TRUE, but the second will give you FALSE. You see, understanding how references and pointers work is important. The textbox's DataSource is holding onto a reference of the old Person instance. You now have two different instances in memory, whether you like it or not.

What do you do about it? Well, as far as I can tell, you can either update your DataSource reference (it did change after all) or you can move your properties over manually so that your references don't change. I'm open to suggestions on other methods here.