Detect the "sender" for Try...Catch

233 views Asked by At

I have a program where i input lot of values from different textboxes and i use try..catch and check every textbox for only entering numerical values. If i enter a different character, it gets it thanks to Catch ex As System.InvalidCastException. After this i want to change the color of the background of the textbox that got the error, something like ex.backcolor = color.red. I have searched for this and tried lot of things but i dont really know how to handle that variable. Appreciate the help, thanks!

1

There are 1 answers

5
jmcilhinney On BEST ANSWER

Based on your description, you are almost certainly doing a few things wrong. I'll provide a full example but I'll provide a direct answer to your question first. You don't need to "detect" anything. The sender parameter IS the object you want. The sender parameter in EVERY event handler is the object that raised the event. That's the whole point. If you are handling events for TextBoxes and you want to change the BackColor of the TextBox that raised the event then you access that TextBox via the sender parameter, e.g.

Dim tb = DirectCast(sender, TextBox)

tb.BackColor = Color.Red

The best way to go about the validation in this case depends on exactly what you need. There's absolutely no reason for any exceptions to be thrown though. Firstly, you need to decide whether you want to prevent the user leaving a control that contains invalid input. If you do then you should handle the Validating event. You can cancel that event to prevent the invalid control losing focus. If you do not cancel the event then the Validated event is raised too, e.g.

Imports System.ComponentModel

Public Class Form1

    Private Sub TextBoxes_Validating(sender As Object, e As CancelEventArgs) Handles TextBox3.Validating,
                                                                                     TextBox2.Validating,
                                                                                     TextBox1.Validating
        Dim tb = DirectCast(sender, TextBox)

        'Check whether the control contains any non-numeric characters.
        If tb.Text.Any(Function(ch) Not Char.IsDigit(ch)) Then
            tb.BackColor = Color.Red
            tb.HideSelection = False
            tb.SelectAll()

            MessageBox.Show("Please enter only numeric characters.",
                            "Invalid Input",
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Error)

            tb.HideSelection = True
            e.Cancel = True
        End If
    End Sub

    Private Sub TextBoxes_Validated(sender As Object, e As EventArgs) Handles TextBox3.Validated,
                                                                              TextBox2.Validated,
                                                                              TextBox1.Validated
        'If this event is raised then the control content is valid so reset the BackColor.

        Dim tb = DirectCast(sender, TextBox)

        tb.BackColor = SystemColors.Window
    End Sub

End Class

As you can see, the methods handle events for multiple controls and the code refers specifically to the control that raised the event. When the user tries to leave a control, its contents is validated and the user notified if they cannot leave because it's invalid.

If you prefer to let the user navigate as they wish but use the BackColor to indicate invalid content immediately, you can handle the TextChanged event instead:

Private Sub TextBoxes_TextChanged(sender As Object, e As EventArgs) Handles TextBox3.TextChanged,
                                                                            TextBox2.TextChanged,
                                                                            TextBox1.TextChanged
    Dim tb = DirectCast(sender, TextBox)

    tb.BackColor = If(tb.Text.Any(Function(ch) Not Char.IsDigit(ch)),
                      Color.Red,
                      SystemColors.Window)
End Sub

EDIT:

Another option is to create your own custom control and build the functionality right into it, so you don't have to handle any events at all, e.g.

Imports System.ComponentModel

Public Class NumericTextBox
    Inherits TextBox

    <DefaultValue(GetType(Color), "Window")>
    Public Property NormalBackColor As Color = SystemColors.Window

    <DefaultValue(GetType(Color), "Red")>
    Public Property ErrorBackColor As Color = Color.Red

    Protected Overrides Sub OnTextChanged(e As EventArgs)
        MyBase.OnTextChanged(e)

        BackColor = If(Text.Any(Function(ch) Not Char.IsDigit(ch)),
                       ErrorBackColor,
                       NormalBackColor)
    End Sub

End Class

Once you build your project, that control will be added to the top of the Toolbox window. You can then add that control to your form instead of regular TextBox controls. Without any additional code, you can type into any of those controls and they will turn red and back again automatically if you add and remove non-numeric characters.

With the properties I've added, you get to choose the two possible BackColor values in the designer, just as you would for other properties. Note that the DefaultValue attributes enable you to right-click those properties in the Toolbox and select Reset to have the properties set back to the specified values.