Reputation: 6131
I'm using Visual Basic .NET developing a windows form application and I want to toggle the enabled property of a Button based on if there is anything in a TextBox. I attempted to setup the DataBinding using the following:
ButtonBack.DataBindings.Add("Enabled", Me.TextBoxValue, "TextLength")
This successfully disables the Button, but whenever anything is typed in the TextBox, the Button never gets enabled. I would much rather do this via DataBindings if possible as opposed to setting the Enabled property manually in the TextChanged or Validating event of the TextBox.
Upvotes: 0
Views: 1004
Reputation: 5380
I usually implement this kind of custom property binding by "subclassing" the control that requires the "new" property, as in your case, TextBox
needs an HasLength
Boolean property (or whatever name you want to give it).
Here's MyTextBox.vb
:
Public Class MyTextBox
Inherits TextBox
Public Event HasLengthChanged As EventHandler
Private _HasLength As Boolean
Public Property HasLength() As Boolean
Get
Return _HasLength
End Get
Set(ByVal value As Boolean)
If value <> _HasLength Then
_HasLength = value
OnHasLengthChanged()
End If
End Set
End Property
Public Sub New()
_HasLength = False
End Sub
Protected Sub OnHasLengthChanged()
RaiseEvent HasLengthChanged(Me, New EventArgs())
End Sub
Protected Overrides Sub OnTextChanged(e As EventArgs)
MyBase.OnTextChanged(e)
HasLength = Not (String.IsNullOrEmpty(Text))
End Sub
End Class
And here's Form1.vb
:
Public Class Form1
Protected Overrides Sub OnLoad(e As EventArgs)
MyBase.OnLoad(e)
ButtonBack.DataBindings.Add("Enabled", Me.MyTextBox1, "HasLength", True, DataSourceUpdateMode.OnPropertyChanged)
End Sub
End Class
Of course, you need a Form with a MyTextBox
instance and a regular Button
instance.
With this method, as soon as the user types something in the textbox, the button becomes enabled, and as soon as the textbox becomes empty, the button is disabled. Please note that I used the DataSourceUpdateMode.OnPropertyChanged
so that the update is done as you type, and not only when the textbox loses focus.
EDIT: I thought I'd add a bit of background about the PropertyNameChanged
pattern in .NET.
There are different ways to let observers know that a property has changed on an object, and most of the time we use the INotifyPropertyChanged
interface, but for controls, the recommended method is still to use the PropertyNameChanged
pattern, which is recognized by .NET, and thus the Binding object can do its job and know when the desired property has changed.
INotifyPropertyChanged
is recommended for data objects that participate in binding.
By the way, the PropertyNameChanged
works in both Windows Forms and WPF.
As reference MSDN:
EDIT 2: I'm a C# programmer, and I've done my best to apply the residual knowledge that I have of VB.NET. Any error is really the result of my being too rusty in VB. Sorry for any inconvenience, but I can assure you that the code runs just fine here.
Upvotes: 2
Reputation: 11801
As @LarsTech stated in his comment, you need to use a property of the TextBox Class that raises changed notifications. The Text
property is the appropriate one to use.
Your request to do this strictly via the binding is possible, but it will still involve using an event handler. As such, I don't see much value in this approach over handling the TextBoxValue.TextChanged
event.
One way of doing this is to use the Binding.Format Event to convert the string of the Text Property to a boolean based on if it contains any characters.
Dim b As Binding = ButtonBack.DataBindings.Add("Enabled", Me.TextBoxValue, "Text", True, DataSourceUpdateMode.OnPropertyChanged)
AddHandler b.Format, Sub(s As Object, args As ConvertEventArgs) args.Value = Not String.IsNullOrEmpty(CStr(args.Value))
Because the binding is two way, if your code changes the ButtonBack.Enabled property, it will send the string representation of the property back to TextBoxValue and its text will read either "True" or "False". This would not be a desirable consequence. To rectify this possibility, the Binding.Parse Event will need to be handled.
AddHandler b.Parse, Sub(s As Object, args As ConvertEventArgs) args.Value = Me.TextBoxValue.Text
Upvotes: 1