question

Hekzdaddy-3952 avatar image
0 Votes"
Hekzdaddy-3952 asked XingyuZhao-MSFT answered

working with Arrays, runtime error

Hello, I am getting an error with the code below. I am trying to enter the number from a txtBox into an array intPin(0), but the error tells me that intPin was nothing. Please advise.

Public Class Form1
Dim intMinPin() As Integer = {7, 5, 0, 0, 6, 3, 4}
Dim intMaxPin() As Integer = {9, 7, 4, 9, 9, 6, 8}
Dim intCount As Integer
Dim val As Integer
Dim intPin() As Integer


 ' Dim intSeries(intMAX_SUBSCRIPT) As Integer

 Private Function ValidateInputFields() As Boolean
     If Not Integer.TryParse(TextBox1.Text, intPin(0)) Then
         MessageBox.Show("Enter numeric digit in textbox1")
         Return False
     ElseIf intPin(0) <= intMinPin(0) >= intMaxPin(0) Then
         Return False
         MessageBox.Show("enter a number between 7 & 9 in Text Box1")
     Else
         Return True
     End If

 End Function
dotnet-visual-basic
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

JasonDaurison-8970 avatar image
1 Vote"
JasonDaurison-8970 answered JasonDaurison-8970 commented

Change:
Const intMAX_SUBSCRIPT As Integer = 7
to:
Const intMAX_SUBSCRIPT As Integer = 6

Since arrays are zero based.
Also move Const intMAX_SUBSCRIPT As Integer = 6, above intPin

· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Dim intMinPin() As Integer = {7, 5, 0, 0, 6, 3, 4}
Dim intMaxPin() As Integer = {9, 7, 4, 9, 9, 6, 8}
Dim intCount As Integer
Dim val As Integer
Const intMAX_SUBSCRIPT As Integer = 6
Dim intPin(intMAX_SUBSCRIPT) As Integer


Private Function ValidateInputFields() As Boolean
If Not Integer.TryParse(TextBox1.Text, intPin(0)) Then
MessageBox.Show("Enter numeric digit in textbox1")
ElseIf intPin(0) <= intMinPin(0) >= intMaxPin(0) Then
Return False
MessageBox.Show("enter a number between 7 and 9")
Else Return True
End If

when I enter a digit outside the range, it does not display the message box, instead it validates the input , any thoughts?

0 Votes 0 ·

Try changing:
ElseIf intPin(0) <= intMinPin(0) >= intMaxPin(0) Then
To:
ElseIf intPin(0) <= intMinPin(0) And intPin(0) >= intMaxPin(0) Then

0 Votes 0 ·
karenpayneoregon avatar image
0 Votes"
karenpayneoregon answered karenpayneoregon edited

The following is conceptual

  • May be too much for you (many coders say I want simple while simple is dependent on how one sees the big picture)

  • May not fit your needs as shown but once understood should provide a base for what you are after

  • You may need to adjust a few things.

  • The custom TextBox could be used in other projects. It only accepts numbers, disallows paste from clipboard. Can be customer farther. Can lose the PIN part for other projects.

A custom TextBox is use, Index property indicates pin order in this case, MinAcceptableValue and MaxAcceptableValue properties indicate what the range can be for the TextBox. GetRange (may need a better name) is used for failed validation in PinValidator.Validate.

PinRange checks in values are in range using a generic extension method

88638-f1.png

Custom Numeric validator TextBox

 Imports System.ComponentModel
    
 Namespace Helpers
    
     Public Class NumericTextbox
         Inherits TextBox
    
         Public Sub New()
             TextAlign = HorizontalAlignment.Right
         End Sub
    
         <Description("PIN Index"), Category("Behavior")>
         Public Property Index() As Integer
         ''' <summary>
         ''' Is PIN in a valid range
         ''' </summary>
         ''' <returns></returns>
         Public ReadOnly Property PinInRange() As Boolean
             Get
                 Return Pin.Between(MinAcceptableValue, MaxAcceptableValue)
             End Get
         End Property
    
         <Description("Min value"), Category("Range")>
         Public Property MinAcceptableValue() As Integer
    
         <Description("Max value"), Category("Range")>
         Public Property MaxAcceptableValue() As Integer
         ''' <summary>
         ''' Get range message
         ''' </summary>
         ''' <returns></returns>
         Public ReadOnly Property GetRange() As String
             Get
                 Return $"PIN{Index} range {MinAcceptableValue} and {MaxAcceptableValue}"
             End Get
         End Property
    
         Const WM_PASTE As Integer = &H302
         ''' <summary>
         ''' PIN value
         ''' </summary>
         ''' <returns></returns>
         <Browsable(False)>
         Public ReadOnly Property Pin As Integer
             Get
                 If String.IsNullOrWhiteSpace(Text) Then
                     Return 0
                 Else
                     Return CInt(Text)
                 End If
             End Get
         End Property
 #Region "OnKeyPress and WndProc"
    
         Protected Overrides Sub OnKeyPress(ByVal e As KeyPressEventArgs)
             Dim value As String = Text
             value = value.Remove(SelectionStart, SelectionLength)
             value = value.Insert(SelectionStart, e.KeyChar)
    
             e.Handled = value.LastIndexOf("-", StringComparison.Ordinal) > 0 _
             Or Not (Char.IsControl(e.KeyChar) OrElse
                         Char.IsDigit(e.KeyChar) OrElse
                     (e.KeyChar = "."c And Not Text.Contains(".") Or e.KeyChar = "."c And MyBase.SelectedText.Contains(".")) OrElse
                     (e.KeyChar = "-"c And SelectionStart = 0))
    
             MyBase.OnKeyPress(e)
    
         End Sub
         Protected Overrides Sub WndProc(ByRef m As Message)
    
             If m.Msg = WM_PASTE Then
    
                 Dim value As String = Text
    
                 value = value.Remove(SelectionStart, SelectionLength)
                 value = value.Insert(SelectionStart, Clipboard.GetText)
    
                 Dim result As Decimal = 0
                 If Not Decimal.TryParse(value, result) Then
                     Return
                 End If
    
             End If
    
             MyBase.WndProc(m)
    
         End Sub
    
 #End Region
     End Class
 End Namespace


Generic extensions (works on numbers and dates)

 Imports System.Runtime.CompilerServices
    
 Namespace Helpers
    
     Public Module GenericExtensions
         <Extension>
         Public Function Between(Of T)(sender As IComparable(Of T), minimumValue As T, maximumValue As T) As Boolean
             Return sender.CompareTo(minimumValue) >= 0 AndAlso sender.CompareTo(maximumValue) <= 0
         End Function
     End Module
 End Namespace

Validator for a button click

 Namespace Helpers
     Public Class PinValidator
         Public Shared Function Validate(sender As List(Of NumericTextbox)) As String
             Return If(sender.Any(Function(box) box.PinInRange = False),
                       "Invalid values" & Environment.NewLine & String.Join(Environment.NewLine,
                                   sender.Where(Function(item) item.PinInRange = False).
                                 Select(Function(x) x.GetRange).ToArray()),
                       "Accepted")
         End Function
     End Class
 End Namespace

Form code

 Imports PinValidate.Helpers
    
 Public Class Form1
     Public PinBoxes As List(Of NumericTextbox)
    
     Private Sub ValidateButton_Click(sender As Object, e As EventArgs) Handles ValidateButton.Click
         MessageBox.Show(PinValidator.Validate(PinBoxes))
     End Sub
    
     Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
         PinBoxes = Controls.OfType(Of NumericTextbox).OrderBy(Function(box) box.Index).ToList()
     End Sub
 End Class

At design time some properties (I changed category from above to fit custom properties onto a small screenshot)


88705-p1.png

By Hand

 Pin1Textbox.Text = "2"
 Pin1Textbox.MinAcceptableValue = 1
 Pin1Textbox.MaxAcceptableValue = 3
 Console.WriteLine(Pin1Textbox.PinInRange)
    
 Pin1Textbox.Text = "20"
 Console.WriteLine(Pin1Textbox.PinInRange)



88725-kpmvp.png


f1.png (6.4 KiB)
p1.png (5.9 KiB)
kpmvp.png (2.0 KiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

XingyuZhao-MSFT avatar image
0 Votes"
XingyuZhao-MSFT answered

Hi @Hekzdaddy-3952 ,
In order to make textbox accept only numbers, you can also take a look at the following code:

     Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
         AddHandler TextBox1.KeyPress, AddressOf TextBox_KeyPress
         AddHandler TextBox2.KeyPress, AddressOf TextBox_KeyPress
         '...
     End Sub
     Private Sub TextBox_KeyPress(ByVal sender As Object, ByVal e As KeyPressEventArgs)
         If Not Char.IsControl(e.KeyChar) AndAlso Not Char.IsDigit(e.KeyChar) AndAlso (e.KeyChar <> "."c) Then
             MessageBox.Show("Enter numeric digit in textbox")
             e.Handled = True
         End If
    
         If (e.KeyChar = "."c) AndAlso ((TryCast(sender, TextBox)).Text.IndexOf("."c) > -1) Then
             MessageBox.Show("Only allow one decimal point")
             e.Handled = True
         End If
     End Sub

Hope it could be helpful.

Best Regards,
Xingyu Zhao


If the answer is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.