Mi è capitato più d'una volta che mi si chiedesse di poter gestire una TextBox in modo da poter accettare solo valori numerici, inibendo ad esempio, tutti i tasti alfanumerici. Per raggiungere lo scopo si possono seguire varie strade: creare uno UserControl personalizzato che si occupi del problema oppure una classe o più semplicemente gestire gli eventi di KeyDown ecc.
Io ho scelto la strada degli Handles anche perchè alla fine mi è sembrata la più flessibile, ma soprattutto la meno invasiva. Infatti non sarà necessario aggiungere nessun componente particolare alle form del progetto, nè scrivere codice per ogni TextBox da gestire, ma semplicemente aggiungere un modulo (o copiare il seguente codice in uno già esistente) e richiamare la routine TextBoxToNumeric.
Altra caratteristica che a me è tornata molto utile è data dal fatto che oltre alla gestione della classica TextBox sarà possibile "convertire in numerico" un qualsiasi controllo di testo come le ComboBox ad esempio.
L'utilizzo è molto semplice, basterà passare alla routine il controllo che si vuole gestire.
Vediamo alcuni esempi:
- Rendere una TextBox generica una "NumericTextBox"
Call TextBoxToNumeric(TextBox1)
- Rendere una ComboBox generica una "NumericCombotBox"
Call TextBoxToNumeric(ComboBox1)
- Possibilità di inserire solo numeri interi e positivi
Call TextBoxToNumeric(TextBox2, isDecimal:=False, Negative:=False)
- In caso di valore "Blank" verrà utilizzato il valore 0
Call TextBoxToNumeric(TextBox3, defalutValue:="0")
- Se viene inserito un valore non corretto non viene sollevato nessun messaggio d'errore.
Call TextBoxToNumeric(TextBox4, ShowError:=False)
Veniao ora al codice vero e proprio. Per poterlo utilizzare basterà copiarlo all'interno di un nuovo modulo o di uno già presente.
Ovviamente le possibilità di personalizzazione sono infinite e potranno essere aggiunti ulteriori Handler od ulteriori controlli o potenziare la Structure con altre proprietà ecc. ecc.
Buon divertimento.
Module NumericBox
'
' Struttura di riferimento
'
Private Structure stTxtNum
Dim isDecimal As Boolean
Dim DefaultValue As String
Dim Negative As Boolean
Dim ShowError As Boolean
End Structure
'
' Oggetto dictionary contenenti le informazioni
'
Dim dic As New Dictionary(Of String, stTxtNum)
Friend Sub TextBoxToNumeric(ByRef sender As Control, _
Optional ByVal isDecimal As Boolean = True, _
Optional ByVal Negative As Boolean = True, _
Optional ByVal defaultValue As String = "", _
Optional ByVal ShowError As Boolean = True)
'***********************************************************************************
'Func.: TextBoxToNumeric (Creazione SB-27/02/2008; Mod.: )
'Desc.: Routine di configurazione e gestione dsegli handles
'DLL. :
'Par. : sender Control Controllo da gestire
' [isDecimal] Boolean Facoltativo. Indica se devo considerare i valori decimali
' [Negative] Boolean Facoltativo. Indoco se devo considerare i valori negativi
' [defaultValue] String Facoltativo. Valore da utilizzare in caso di campo vuoto
' [ShowError] Boolean Facoltativo. Indica se va mostrato un messaggio d'errore
'Ret. :
'***********************************************************************************
Dim st As New stTxtNum ' Struttura con le informazioni del controllo
If Not dic.TryGetValue(sender.Name, st) Then
dic.Add(sender.Name, st)
AddHandler sender.KeyDown, AddressOf KeyDown
AddHandler sender.Validating, AddressOf Validating
End If
With st
.isDecimal = isDecimal
.DefaultValue = defaultValue
.Negative = Negative
.ShowError = ShowError
End With
'
' Aggiungo alla collection
'
dic.Item(sender.Name) = st
End Sub
#Region "Handles"
Private Sub Validating(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs)
Dim r As New stTxtNum
'
' Tento di recuperare le informazioni sul controllo
'
Call dic.TryGetValue(sender.name, r)
'
' Prima di tutto verifico se sia numerico
'
If Not sender.text = "" AndAlso Not IsNumeric(sender.Text) Then
e.Cancel = True
If r.ShowError Then MsgBox("Valore non valido")
End If
'
' Eseguo i controlli
'
If Not r.DefaultValue = "" AndAlso sender.text = "" Then
sender.text = r.DefaultValue
End If
If Not r.Negative AndAlso Val(sender.text) < 0 Then
If r.ShowError Then MsgBox("Valore non valido")
e.Cancel = True
End If
End Sub
#End Region
Friend Function TextBoxToNumericDispose(ByRef sender As TextBox) As Boolean
'***********************************************************************************
'Func.: TextBoxToNumericDispose (Creazione SB-27/02/2008; Mod.: )
'Desc.: Rimuove la gestione
'DLL. :
'Par. : sender Control Controllo da gestire
'Ret. :
'***********************************************************************************
Dim r As New stTxtNum
'
' Rimuovo ogni gestione
'
Try
RemoveHandler sender.KeyDown, AddressOf KeyDown
dic.Remove(sender.Name)
Catch ex As Exception
End Try
End Function
Private Sub KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs)
Dim r As New stTxtNum
Call dic.TryGetValue(sender.name, r)
Select Case e.KeyCode
Case Keys.NumPad0 To Keys.NumPad9, Keys.D0 To Keys.D9 ' Tasti numerici
e.SuppressKeyPress = False
Case Keys.OemMinus, Keys.Oemplus ' Gestione del segno
e.SuppressKeyPress = (Not r.Negative And e.KeyCode = Keys.OemMinus)
Case Keys.Decimal, Keys.Oemcomma, Keys.Separator ' Seperatore decimale/migliaia
If dic.TryGetValue(sender.name, r) Then
e.SuppressKeyPress = Not r.isDecimal
End If
Case Keys.Home, Keys.End, Keys.Left, Keys.Right, Keys.Up, Keys.Down ' Tasti di direzione
Case Keys.Delete, Keys.Back, Keys.Shift, Keys.Control, Keys.Enter, Keys.Insert
Case Else
e.SuppressKeyPress = True
End Select
r = Nothing
End Sub
End Module