Let's say you have the following class:
51 Public Class Person
52 Private _name As String
53
54 Public Event NameChanged As EventHandler
55
56 Public Property Name() As String
57 Get
58 Return _name
59 End Get
60 Set(ByVal value As String)
61 _name = value
62 OnNameChanged(EventArgs.Empty)
63 End Set
64 End Property
65
66 Protected Sub OnNameChanged(ByVal e As EventArgs)
67 RaiseEvent NameChanged(Me, e)
68 End Sub
69 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.
3 Public Class Form1
4 Private txtName As New TextBox
5 Private _person As New Person
6
7 Public Sub New()
8 ' This call is required by the Windows Form Designer.
9 InitializeComponent()
10
11 ' Add any initialization after the InitializeComponent() call.
12 Me.Controls.Add(txtName)
13
14 _person.Name = "cool"
15 txtName.DataBindings.Add("Text", _person, "Name")
16 End Sub
17
18 Private Sub Form_Click(ByVal sender As Object, ByVal e As EventArgs) _
19 Handles Me.Click
20 _person.Name = "clicked"
21 End Sub
22 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:
18 Private Sub Form_Click(ByVal sender As Object, ByVal e As EventArgs) _
19 Handles Me.Click
20
21 Dim newPerson As New Person
22 newPerson.Name = "new person"
23 _person = newPerson
24 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:
18 Private Sub Form_Click(ByVal sender As Object, ByVal e As EventArgs) _
19 Handles Me.Click
20
21 Dim newPerson As New Person
22 newPerson.Name = "new person"
23
24 Debug.WriteLine("Are references equal? " & Object.ReferenceEquals(txtName.DataBindings("Text").DataSource, _person))
25 _person = newPerson
26 Debug.WriteLine("Are references equal? " & Object.ReferenceEquals(txtName.DataBindings("Text").DataSource, _person))
27 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.