I have a class with a property that I need to bind to a form TextBox in VB.NET. So far none of my attempts will have the TextBox updating in real time from the object properties.
I have the following code in my class
Public Class Servo
Implements System.ComponentModel.INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Private _ServoID As Integer
Property ServoID() As Integer
Get
Return _ServoID
End Get
Set(ByVal Value As Integer)
_ServoID = Value
Call LoadModelInfo()
RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs("ServoID"))
End Set
End Property
End Class
On the form load event I have the binding code
TextBoxCurrServoID.DataBindings.Add("Text", CurrentServoFormServoManager, "ServoID", False, DataSourceUpdateMode.OnPropertyChanged)
The object from the class is declared in module for global variables
Public CurrentServoFormServoManager As RobotModel2.Servo = New RobotModel2.Servo
The object/class works fine, I can write and read data from it's properties, no problems. If I attach/create a BindingList with it and set that as the datasource to a DataGridView the cells in the DataGridView update properly. I just can't seem to get it working with a TextBox. I can't see what I might be missing. Thanks.
EDIT - MORE INFORMATION:
After further research I found a similar post which mentioned that binding to a property of a class while the property is null can cause it not to work. You have to have data there BEFORE binding.
I added a button on the form and moved the binding code there and commented it out on the load event. I then load the form. Populate the CurrentServoFormServoManager object with data, then click the button to bind the TextBoxes to CurrentServoFormServoManager properties. And that works. I can programmatically change the data and the TextBoxes update.
The problem is. I cannot really use this as a solution. The object CurrentServoFormServoManager is constantly being destroyed and remade in this program. As soon as you make it = nothing or = to a new servo object the databinding breaks and has to be reset. I cannot do this since that event is happening outside of the form control. It is triggered by packets coming in from the serial port at different times. IE: I have to hang the form in order to wait for the serial packet to then rebind the data. And that is the solution I'm trying to get away from in the code.
I also attempted to populate the servo object, then bind the TextBoxes, and then only update the data without rebuilding the object and that can be updated from buttons on the form, but incoming threadsafe data from a serial packet will not update the TextBoxes. The data is properly updating in the object properties, and the datagrid which is bound through a BindingList updates fine, but the TextBoxes won't.
So... I'm still without a solution on how to bind TextBoxes to the properties of a class object that can be preset and left in place.
Possibly not the best solution, but if you are creating and destroying Servo
objects (i.e. constantly changing the CurrentServoFormServoManager
reference), then perhaps you need a container class that holds the Servo
reference and exposes its properties by delegation, then raise an event when either the reference or the property changes.
e.g. container class:
Imports System.ComponentModel
Public Class ServoContainer
Implements System.ComponentModel.INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Private WithEvents _servo As Servo
Sub New()
_servo = New Servo
End Sub
Property Servo As Servo
Get
Return _servo
End Get
Set(value As Servo)
_servo = value
RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs("ServoID"))
End Set
End Property
Private Sub _servo_PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Handles _servo.PropertyChanged
RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs("ServoID"))
End Sub
Property ServoID As Integer
Get
Return _servo.ServoID
End Get
Set(value As Integer)
_servo.ServoID = value
End Set
End Property
End Class
Instantiating the container:
Public CurrentServoContainer As ServoContainer = New ServoContainer
Replace your current textbox binding as follows:
TextBoxCurrServoID.DataBindings.Add("Text", CurrentServoContainer, "ServoID", False, DataSourceUpdateMode.OnPropertyChanged)
Now, both of the following lines will update the textbox:
CurrentServoContainer.Servo.ServoID = 99
and
CurrentServoContainer.Servo = New Servo With {.ServoID = 98} 'replace with your actual constructor'