none
Textbox que solo admita números , hacerlo en una función genérica RRS feed

  • Pregunta

  • Buenas , tengo esta función que cogí por internet para solo permitir introducir números , me gustaría ponerla en una clase para poder usarla de forma genérica en textbox o en otros componentes.

    Lo he puesto en una clase que se llama utilesSistema por lo que tengo este código.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace XXX.clases
    {
        static class utilesSistema
        {
            public static void soloNumerosEnTextbox(object sender, KeyPressEventArgs e)
            {
                //Para obligar a que sólo se introduzcan números 
                if (Char.IsDigit(e.KeyChar))
                {
                    e.Handled = false;
                }
                else
                    if (Char.IsControl(e.KeyChar)) //permitir teclas de control como retroceso 
                    {
                        e.Handled = false;
                    }
                    else
                    {
                        //el resto de teclas pulsadas se desactivan 
                        e.Handled = true;
                    }
            } 
    
        }
    }

    Me gustaría saber si esta es la forma correcta y como debo llamarlo desde el formulario donde tengo el componente.

    Gracias

    jueves, 10 de marzo de 2016 21:21

Respuestas

  • Sinceramente, cada vez veo más claro que lo que mejor te vendría es un control personalizado.

    Mira este ejemplo:

        public class NumericTextBox : TextBox
        {
    
            public NumericTextBox()
            {
                DecimalSeparator = CultureInfo.CurrentUICulture.NumberFormat.NumberDecimalSeparator[0];
                GroupSeparator = CultureInfo.CurrentUICulture.NumberFormat.NumberGroupSeparator[0];            
                AllowDecimalValues = true;
            }
    
            public char DecimalSeparator { get; set; }
    
            public char GroupSeparator { get; set; }
    
            public bool ShowGroupSeparator { get; set; }
    
            public bool AllowDecimalValues { get; set; }
    
            public decimal DecimalValue => decimal.Parse($"0{Text}", NumberFormat);
    
            public int IntegerValue => int.Parse($"0{Text}", NumberFormat);
    
            private bool _decimalKeyPressed;
    
            protected override void OnKeyDown(KeyEventArgs e)
            {
                base.OnKeyDown(e);
                _decimalKeyPressed = e.KeyCode == Keys.Decimal;
            }
    
            protected override void OnKeyPress(KeyPressEventArgs e)
            {
                base.OnKeyPress(e);
                if (_decimalKeyPressed)
                {
                    e.KeyChar = DecimalSeparator;
                }
                if (char.IsControl(e.KeyChar) || char.IsDigit(e.KeyChar))
                {
                    return;
                }
                if (AllowDecimalValues && e.KeyChar == DecimalSeparator 
                    && Text.IndexOf(DecimalSeparator) < 0)
                {
                    return;
                }
    
                e.Handled = true;
            }
    
            protected override void OnEnter(EventArgs e)
            {
                if (!string.IsNullOrEmpty(Text))
                {
                    Text = DecimalValue.ToString("0.########", NumberFormat);
                }
                base.OnEnter(e);
            }
    
            protected override void OnLeave(EventArgs e)
            {
                base.OnLeave(e);
                if (!string.IsNullOrEmpty(Text))
                {
                    string format = ShowGroupSeparator ? "#,##0.########" : "0.########";
                    Text = DecimalValue.ToString(format, NumberFormat);
                }
            }
    
            private NumberFormatInfo NumberFormat => new NumberFormatInfo()
            {
                NumberDecimalSeparator = DecimalSeparator.ToString(),
                NumberGroupSeparator = GroupSeparator.ToString()
            };
        }
    

    Este control te proporciona propiedades para indicar el separador decimal (DecimalSeparator), el separador de miles (GroupSeparator), si mostrar o no el separador de miles (ShowGroupSeparator) o si admite decimales o únicamente números enteros (AllowDecimalValues).

    También tiene dos propiedades que devuelven directamente el valor del número como Decimal o Integer (DecimalValue, IntegerValue).

    Por último reemplaza el carácter de la tecla del punto del teclado numérico por el carácter indicado como separador decimal.

    Podrías ir añadiéndole funcionalidad para, por ejemplo, soportar números negativos o indicar la precisión de decimales con la que trabajar.


    Píldoras .NET
    Artículos, tutoriales y ejemplos de código .NET

    Píldoras JS
    Artículos, tutoriales y ejemplos de código JavaScript, HTML5, CSS3, ...

    sábado, 12 de marzo de 2016 7:18

Todas las respuestas

  • Pues así sirve ciertamente, pero solamente sirve para Windows Forms.  No es una validación que le servirá para, por ejemplo, WPF porque el tipo de argumentos es distinto.

    Jose R. MCP
    Code Samples

    jueves, 10 de marzo de 2016 21:30
    Moderador
  • hola

    en la clase deberias definir la funcionalidad no al firma del evento

    la clase podria ser

    static class utilesSistema
    {
    	public static bool soloNumerosEnTextbox(char keyChar)
    	{
    		//Para obligar a que sólo se introduzcan números 
    		if (Char.IsDigit(keyChar))
    		{
    			return false;
    		}
    		else
    			if (Char.IsControl(keyChar)) //permitir teclas de control como retroceso 
    			{
    				return false;
    			}
    			else
    			{
    				//el resto de teclas pulsadas se desactivan 
    				return true;
    			}
    	} 
    
    }

    y la usarias

    public static bool TextBox1_KeyDown(object sender, KeyPressEventArgs e)
    {
    	e.Handled = utilesSistema.soloNumerosEnTextbox(e.KeyChar);
    }

    o sea le pasas un caracter y devolvera si es valido o no

    pero el evento lo defines en el form

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    jueves, 10 de marzo de 2016 21:38
  • hola

    en la clase deberias definir la funcionalidad no al firma del evento

    la clase podria ser

    static class utilesSistema
    {
    	public static bool soloNumerosEnTextbox(char keyChar)
    	{
    		//Para obligar a que sólo se introduzcan números 
    		if (Char.IsDigit(keyChar))
    		{
    			return false;
    		}
    		else
    			if (Char.IsControl(keyChar)) //permitir teclas de control como retroceso 
    			{
    				return false;
    			}
    			else
    			{
    				//el resto de teclas pulsadas se desactivan 
    				return true;
    			}
    	} 
    
    }

    y la usarias

    public static bool TextBox1_KeyDown(object sender, KeyPressEventArgs e)
    {
    	e.Handled = utilesSistema.soloNumerosEnTextbox(e.KeyChar);
    }

    o sea le pasas un caracter y devolvera si es valido o no

    pero el evento lo defines en el form

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    OK me da error al usar lo , me dice que no existe e.keyChar las opciones que me da son e.keydata o e.keyValue pero en ambas me da error al compilar.

    Gracias.

    jueves, 10 de marzo de 2016 22:20
  • ok cambia de evento y usa el KeyPress

    public static bool TextBox1_KeyPress(object sender, KeyPressEventArgs e)
    {
    	e.Handled = utilesSistema.soloNumerosEnTextbox(e.KeyChar);
    }

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    viernes, 11 de marzo de 2016 3:27
  • Y ¿por qué no encapsulas la funcionalidad en un control personalizado en lugar de en un método?

    Por ejemplo:

        public class IntegerTextBox: TextBox
        {
            protected override void OnKeyPress(KeyPressEventArgs e)
            {
                base.OnKeyPress(e);
                if (!(char.IsControl(e.KeyChar) || char.IsDigit(e.KeyChar)))
                {
                    e.Handled = true;
                }
            }
        }

    De esta forma tendrías un nuevo control IntegerTextBox que simplemente tendrías que añadir a tus formularios para tener la funcionalidad.


    Píldoras .NET
    Artículos, tutoriales y ejemplos de código .NET

    Píldoras JS
    Artículos, tutoriales y ejemplos de código JavaScript, HTML5, CSS3, ...


    viernes, 11 de marzo de 2016 8:25
  • Y ¿por qué no encapsulas la funcionalidad en un control personalizado en lugar de en un método?

    Por ejemplo:

        public class IntegerTextBox: TextBox
        {
            protected override void OnKeyPress(KeyPressEventArgs e)
            {
                base.OnKeyPress(e);
                if (!(char.IsControl(e.KeyChar) || char.IsDigit(e.KeyChar)))
                {
                    e.Handled = true;
                }
            }
        }

    De esta forma tendrías un nuevo control IntegerTextBox que simplemente tendrías que añadir a tus formularios para tener la funcionalidad.


    Píldoras .NET
    Artículos, tutoriales y ejemplos de código .NET

    Píldoras JS
    Artículos, tutoriales y ejemplos de código JavaScript, HTML5, CSS3, ...


    Gracias por la respuesta , en principio lo haré de la otra forma.

    viernes, 11 de marzo de 2016 17:32
  • Ok gracias asin lo he hecho.

    Ahora he modificado la función para que acepte el simbolo decimal en mi caso quiero que solo acepte el "." de momento he hecho esta función solo permite números y los caracteres de la coma y el punto , pero no veo como restringir que solo deje poner el punto o hacer que si se pone una "coma" devuelva un "punto".

    El código que tengo este

       public static bool soloNumerosEnTextbox(char keyChar)
            {
                
                if (char.IsPunctuation(keyChar))
                {
                    return false;            
                }
                //Para obligar a que sólo se introduzcan números 
                else if (Char.IsDigit(keyChar))
                {
                    return false;
                }
                else
                {
                    if (Char.IsControl(keyChar)) //permitir teclas de control como retroceso 
                    {
                        return false;
                    }
                    else
                    {
                        //el resto de teclas pulsadas se desactivan 
                        return true;
                    }
                }
            } 
    


    Gracias

    viernes, 11 de marzo de 2016 17:33
  • Hola,

    Mira aquí, creo que explica todo lo que necesitas, como ponerlo en una clase propia, como limitar solo numero, con solo una coma decimal y signos mas y menos.

    Un Saludo


    Es de buena educación dar las gracias cuando te ayudan, si alguna respuesta te ha sido de utilidad agradécelo marcandola como útil.
    Blog

    viernes, 11 de marzo de 2016 20:11
  • Sinceramente, cada vez veo más claro que lo que mejor te vendría es un control personalizado.

    Mira este ejemplo:

        public class NumericTextBox : TextBox
        {
    
            public NumericTextBox()
            {
                DecimalSeparator = CultureInfo.CurrentUICulture.NumberFormat.NumberDecimalSeparator[0];
                GroupSeparator = CultureInfo.CurrentUICulture.NumberFormat.NumberGroupSeparator[0];            
                AllowDecimalValues = true;
            }
    
            public char DecimalSeparator { get; set; }
    
            public char GroupSeparator { get; set; }
    
            public bool ShowGroupSeparator { get; set; }
    
            public bool AllowDecimalValues { get; set; }
    
            public decimal DecimalValue => decimal.Parse($"0{Text}", NumberFormat);
    
            public int IntegerValue => int.Parse($"0{Text}", NumberFormat);
    
            private bool _decimalKeyPressed;
    
            protected override void OnKeyDown(KeyEventArgs e)
            {
                base.OnKeyDown(e);
                _decimalKeyPressed = e.KeyCode == Keys.Decimal;
            }
    
            protected override void OnKeyPress(KeyPressEventArgs e)
            {
                base.OnKeyPress(e);
                if (_decimalKeyPressed)
                {
                    e.KeyChar = DecimalSeparator;
                }
                if (char.IsControl(e.KeyChar) || char.IsDigit(e.KeyChar))
                {
                    return;
                }
                if (AllowDecimalValues && e.KeyChar == DecimalSeparator 
                    && Text.IndexOf(DecimalSeparator) < 0)
                {
                    return;
                }
    
                e.Handled = true;
            }
    
            protected override void OnEnter(EventArgs e)
            {
                if (!string.IsNullOrEmpty(Text))
                {
                    Text = DecimalValue.ToString("0.########", NumberFormat);
                }
                base.OnEnter(e);
            }
    
            protected override void OnLeave(EventArgs e)
            {
                base.OnLeave(e);
                if (!string.IsNullOrEmpty(Text))
                {
                    string format = ShowGroupSeparator ? "#,##0.########" : "0.########";
                    Text = DecimalValue.ToString(format, NumberFormat);
                }
            }
    
            private NumberFormatInfo NumberFormat => new NumberFormatInfo()
            {
                NumberDecimalSeparator = DecimalSeparator.ToString(),
                NumberGroupSeparator = GroupSeparator.ToString()
            };
        }
    

    Este control te proporciona propiedades para indicar el separador decimal (DecimalSeparator), el separador de miles (GroupSeparator), si mostrar o no el separador de miles (ShowGroupSeparator) o si admite decimales o únicamente números enteros (AllowDecimalValues).

    También tiene dos propiedades que devuelven directamente el valor del número como Decimal o Integer (DecimalValue, IntegerValue).

    Por último reemplaza el carácter de la tecla del punto del teclado numérico por el carácter indicado como separador decimal.

    Podrías ir añadiéndole funcionalidad para, por ejemplo, soportar números negativos o indicar la precisión de decimales con la que trabajar.


    Píldoras .NET
    Artículos, tutoriales y ejemplos de código .NET

    Píldoras JS
    Artículos, tutoriales y ejemplos de código JavaScript, HTML5, CSS3, ...

    sábado, 12 de marzo de 2016 7:18