Sandro Bizioli


Chi sogna di giorno conosce molte cose che sfuggono a chi sogna soltanto di notte. (E.A.Poe)
Mappa

Convertire una TextBox in una TextBox Numerica

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

Categoria: VB.Net
mercoledì, 27 feb 2008 Ore. 17.43
Statistiche
  • Views Home Page: 111.567
  • Views Posts: 568.348
  • Views Gallerie: 117.624
  • n° Posts: 227
  • n° Commenti: 222
Copyright © 2002-2007 - Blogs 2.0
dotNetHell.it | Home Page Blogs
ASP.NET 2.0 Windows 2003