Apply code to multiple textboxes

bones

Well-known member
Joined
Aug 23, 2014
Messages
143
Programming Experience
Beginner
This is some of jmcilhinney's work that I found elsewhere. I would like to apply this to several text boxes on a form.

This link talks about that process but uses slightly different code that I have been advised to avoid. Force only number entering in textboxes-VBForums

Ok.. the code example below specifically refers to textbox name. So my question is :

How can this code be modified so that it could be used in the method of applying the code to multiple textboxes as spoken about in the posted link above.
Of course I could do it manually on each textbox but I would like to avoid that and end up with code that I can then use throughout my app as the need arises. I have modified it slightly already to fit my use..but only the textbox name and length of accepted values.

VB.NET:
Private Sub TextBox16_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox16.KeyPress
        ' Prevent non numeric characters from being entered in textbox
        Dim keyChar = e.KeyChar


        If Char.IsControl(keyChar) Then
            'Allow all control characters.
        ElseIf Char.IsDigit(keyChar) OrElse keyChar = "."c Then
            Dim text = Me.TextBox16.Text
            Dim selectionStart = Me.TextBox16.SelectionStart
            Dim selectionLength = Me.TextBox16.SelectionLength


            text = text.Substring(0, selectionStart) & keyChar & text.Substring(selectionStart + selectionLength)


            If Integer.TryParse(text, New Integer) AndAlso text.Length > 4 Then
                'Reject an integer that is longer than 16 digits.
                e.Handled = True
            ElseIf Double.TryParse(text, New Double) AndAlso text.IndexOf("."c) < text.Length - 4 Then
                'Reject a real number with two many decimal places.
                e.Handled = True
            End If
        Else
            'Reject all other characters.
            e.Handled = True
        End If
    End Sub
 
Just create a NumericTextBox:

Public Class NumericTextBox
    Inherits TextBox


    Private Sub NumericTextBox_KeyPress(sender As NumericTextBox, e As KeyPressEventArgs) Handles Me.KeyPress
        If Char.IsControl(e.KeyChar) Then
            'Allow all control characters.
        ElseIf Char.IsDigit(e.KeyChar) OrElse e.KeyChar = "."c Then
            Dim text = sender.Text
            Dim selectionStart = sender.SelectionStart
            Dim selectionLength = sender.SelectionLength

            text = text.Substring(0, selectionStart) & e.KeyChar & text.Substring(selectionStart + selectionLength)

            If Integer.TryParse(text, New Integer) AndAlso text.Length > 4 Then
                'Reject an integer that is longer than 16 digits.
                e.Handled = True
            ElseIf Double.TryParse(text, New Double) AndAlso text.IndexOf("."c) < text.Length - 4 Then
                'Reject a real number with two many decimal places.
                e.Handled = True
            End If
        Else
            'Reject all other characters.
            e.Handled = True
        End If
    End Sub

End Class


But that code looks messy and it's not clear what you want to achieve. There is almost certainly a better way to do what you want, if you would care to explain what exactly you want the textbox to do.
 
My text boxes need to accept whole numbers and decimals only

When I tried out the code I posted what I saw it did and liked was that if you tried to enter a letter in the box, it simply wouldn't take it. NOTE, that code was designed for a specific purpose that someone else asked to have solved. I just tweaked it a bit and tried it out.
 
I don't understand the construction of numeric textbox. Is it a control that I don't see in my toolbox? Does the code you provided turn a regular text box into a numeric textbox?

Please enlighten me.

I'm looking at this How to: Create a Numeric Text Box

Those examples frustrate me. It looks like a lot of code to handle the situation. I believe more code than what I'm currently using to handle the situation.. What I was striving for was less code.
 
Last edited:
I don't understand the construction of numeric textbox. Is it a control that I don't see in my toolbox? Does the code you provided turn a regular text box into a numeric textbox?

Please enlighten me.

If you define a class that inherits TextBox or any other control class then your class becomes a control. Once you've built your project, that control will automatically appear in the Toolbox for that solution. You then treat it exactly like you do any other control. It doesn't do anything to any regular TextBox. You use it in place of a regular TextBox.

I would suggest that you use my SimpleNumberBox class from here:

Numeric Text Box

You can simply add that class code file to your project and away you go. That class will allow any positive or negative number with or without decimal places.
 
I'm looking at this How to: Create a Numeric Text Box

Those examples frustrate me. It looks like a lot of code to handle the situation. I believe more code than what I'm currently using to handle the situation.. What I was striving for was less code.

The good thing about creating a custom control is that any complexity is encapsulated within the control and then the code to use the custom control is very simple.

While we all want our code to be simple, don't assume that it always can be. Most simple implementations of numeric text boxes I see completely ignore the fact that the user can paste arbitrary text into the control. They also don't really consider what to do with negative signs and decimal points. Many will exclude both altogether or allow any number of either in any position. My SimpleNumberBox prevents pasting invalid text, allows only a single leading negative sign and only a single decimal point. Even then, it doesn't consider thousand separators or what happens if the user enters "-.". Ensuring that text is numeric is not the simple task that many seem to think it is. They often think just about the obvious and ignore edge cases. Edge cases are usually the reason for most of your code.
 
I grabbed that file. I have never done this process before. Please advise what to do to get this in my project.
 
My text boxes need to accept whole numbers and decimals only

Then it's even simpler:

Public Class NumericTextBox
    Inherits TextBox ' Inherit from a standard textbox

    Public Property Value As Decimal ' Add a new decimal value property

    Public Overrides Property Text As String ' Override the textbox's Text property to handle only numeric values and reflect the Value property.
        Get
            Return Value.ToString()
        End Get
        Set(_value As String)
            If IsNumeric(_value) Then
                Value = CDec(_value)
            Else
                Throw New ArgumentException("Value must be numeric.", "Text")
            End If
        End Set
    End Property

End Class
 
I grabbed that file. I have never done this process before. Please advise what to do to get this in my project.

Download the file, open your project in VS, right-click the project in the Solution Explorer, select Add -> Existing Item, select the downloaded file, build your project. You'll then find the new control at the top of the Toolbox and you can use it like any other control.
 
Here's that class code with some comments that may make it easier to understand:
Imports System.Globalization

Public Class SimpleNumberBox
    Inherits System.Windows.Forms.TextBox

    'The Windows message received when a paste operation is performed.
    Private Const WM_PASTE As Integer = &H302

    Protected Overrides Sub OnKeyPress(ByVal e As System.Windows.Forms.KeyPressEventArgs)
        Dim keyChar = e.KeyChar
        Dim formatInfo = NumberFormatInfo.CurrentInfo

        'Always allow control characters and digits and
        'allow a ngative sign or decimal point only if the resulting text would pass validation.
        If Char.IsControl(keyChar) OrElse _
           Char.IsDigit(keyChar) OrElse _
           ((keyChar = formatInfo.NegativeSign OrElse _
             keyChar = formatInfo.NumberDecimalSeparator) AndAlso _
            Me.ValidateText(keyChar)) Then
            MyBase.OnKeyPress(e)
        Else
            'Don't accept the input.
            e.Handled = True
        End If
    End Sub

    Protected Overrides Sub OnValidated(ByVal e As System.EventArgs)
        'Clear the control when the user navigates away if it does not contain a valid number.
        If Not Decimal.TryParse(Me.Text, New Decimal) Then
            Me.Clear()
        End If

        MyBase.OnValidated(e)
    End Sub

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        'Only process a paste message if the Clipboard contains text and the result would pass validation
        If m.Msg <> WM_PASTE OrElse _
           Not Clipboard.ContainsText() OrElse _
           Me.ValidateText(Clipboard.GetText()) Then
            MyBase.WndProc(m)
        End If
    End Sub

    Private Function ValidateText(ByVal newText As String) As Boolean
        Dim isValid = True
        Dim currentText = Me.Text
        Dim selectionStart = Me.SelectionStart

        'Determine what the text will look like if the input is accepted.
        Dim proposedText = currentText.Substring(0, selectionStart) & _
                           newText & _
                           currentText.Substring(selectionStart + Me.SelectionLength)

        'Accept the input if it produces a valid number, just a negative sign,
        'just a decimal point or a negative sign followed by a decimal point.
        If Not Decimal.TryParse(proposedText, _
                                NumberStyles.AllowLeadingSign Or NumberStyles.AllowDecimalPoint, _
                                Nothing, _
                                New Decimal) Then
            Dim formatInfo = NumberFormatInfo.CurrentInfo
            Dim negativeSign = formatInfo.NegativeSign
            Dim decimalSeparator = formatInfo.NumberDecimalSeparator

            isValid = (proposedText = negativeSign) OrElse _
                      (proposedText = decimalSeparator) OrElse _
                      (proposedText = negativeSign & decimalSeparator)
        End If

        Return isValid
    End Function

End Class
 
Download the file, open your project in VS, right-click the project in the Solution Explorer, select Add -> Existing Item, select the downloaded file, build your project. You'll then find the new control at the top of the Toolbox and you can use it like any other control.


Got it! Awesome. Learned something new and got a new tool to boot :nevreness:

One more dumb question. Is there a way to convert the half dozen or so text boxes I have on the form to be numeric or do I have to recreate them and recode them all? They have formulas tied to them...
 
One more dumb question. Is there a way to convert the half dozen or so text boxes I have on the form to be numeric or do I have to recreate them and recode them all? They have formulas tied to them...

Anything you do in the designer generates code in the designer code file. Conversely, changes you make to the designer code file will be reflected in the designer. It's potentially risky to meddle with the designer code file because the wrong change can break your form, so be careful.

Select your project in the Solution Explorer and click the Show All Files button. Expand the node for your form and then double-click the Designer.vb node to open the designer code file. You can now change the type of any fields declared as TextBox to SimpleNumberBox. You'll also have to change the type where the instance is created, which will be flagged as an error when you change the type of the field.
 
Anything you do in the designer generates code in the designer code file. Conversely, changes you make to the designer code file will be reflected in the designer. It's potentially risky to meddle with the designer code file because the wrong change can break your form, so be careful.

Select your project in the Solution Explorer and click the Show All Files button. Expand the node for your form and then double-click the Designer.vb node to open the designer code file. You can now change the type of any fields declared as TextBox to SimpleNumberBox. You'll also have to change the type where the instance is created, which will be flagged as an error when you change the type of the field.

Ok.. here's a portion of the designer.vb for that form. I want to be certain I have this correct so I don't waste my form...

So let's use this line as a sample Me.TextBox14 = New System.Windows.Forms.TextBox()

Please show me the correct edited line for that box and I'l be good to go... A little guy shy about diving into this..
 
Ok.. here's a portion of the designer.vb for that form. I want to be certain I have this correct so I don't waste my form...

So let's use this line as a sample Me.TextBox14 = New System.Windows.Forms.TextBox()

Please show me the correct edited line for that box and I'l be good to go... A little guy shy about diving into this..

You can change this:
Me.TextBox14 = New System.Windows.Forms.TextBox()
to this:
Me.TextBox14 = New SimpleNumberBox()
but you will also have to change the declaration of TextBox14, which will look something like this:
Friend TextBox14 As System.Windows.Forms.TextBox
to:
Friend TextBox14 As SimpleNumberBox
 
You can change this:
Me.TextBox14 = New System.Windows.Forms.TextBox()
to this:
Me.TextBox14 = New SimpleNumberBox()
but you will also have to change the declaration of TextBox14, which will look something like this:
Friend TextBox14 As System.Windows.Forms.TextBox
to:
Friend TextBox14 As SimpleNumberBox

That's kind of what I thought but I needed to be sure..

One more critical question regarding formulas.. I think they will be fine but hey.... can't hurt to ask first.

The text boxes are referenced by name in formulas. Will the type conversion cause issues there?

Actually 2 questions... Looks like I can do a find/replace.... right?
 
Back
Top