644 votes

Comment créer une zone de texte qui n'accepte que des chiffres ?

J'ai une application Windows forms avec un contrôle de zone de texte qui ne doit accepter que des valeurs entières. Dans le passé, j'ai effectué ce type de validation en surchargeant l'événement KeyPress et en supprimant simplement les caractères qui ne correspondaient pas à la spécification. J'ai examiné le contrôle MaskedTextBox, mais j'aimerais une solution plus générale qui pourrait fonctionner avec une expression régulière, ou dépendre des valeurs d'autres contrôles.

L'idéal serait que l'appui sur un caractère non numérique ne produise aucun résultat ou que l'utilisateur soit immédiatement informé du caractère non valide.

13 votes

Nombres ou chiffres ? grande différence : même les nombres entiers peuvent devenir négatifs

8 votes

La question visait les nombres incluant l'ensemble des nombres rationnels.

889voto

Matt Hamilton Points 98268

Deux options :

  1. Utilisez plutôt un NumericUpDown. Le NumericUpDown effectue le filtrage pour vous, ce qui est agréable. Bien entendu, cela permet également à vos utilisateurs d'utiliser les flèches haut et bas du clavier pour incrémenter et décrémenter la valeur actuelle.

  2. Gérer les événements clavier appropriés pour empêcher toute saisie autre que numérique. J'ai eu du succès avec ces deux gestionnaires d'événements sur une TextBox standard :

    private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
    {
        if (!char.IsControl(e.KeyChar) 
            && !char.IsDigit(e.KeyChar) 
            && e.KeyChar != '.')
        {
            e.Handled = true;
        }
    
        // only allow one decimal point
        if (e.KeyChar == '.' 
            && (sender as TextBox).Text.IndexOf('.') > -1)
        {
            e.Handled = true;
        }
    }

Vous pouvez supprimer la vérification de "." (et la vérification subséquente de plus d'un ".") si votre TextBox ne doit pas autoriser les décimales. Vous pouvez également ajouter une vérification pour '-' si votre TextBox doit permettre des valeurs négatives.

Si vous voulez limiter l'utilisateur pour le nombre de chiffres, utilisez : textBox1.MaxLength = 2 ; // ceci permettra à l'utilisateur d'entrer seulement 2 chiffres.

2 votes

J'avais oublié que la commande numérique haut-bas existait. C'est en fait ce que je devrais utiliser ici au lieu d'une zone de texte. À l'avenir, lorsque j'aurai une validation plus compliquée, j'utiliserai la propriété handled avec l'événement KeyPress.

8 votes

Le seul inconvénient de NumericUpDown est qu'il ne fournit aucun retour d'information lorsque vous entrez une valeur en dehors des valeurs maximales ou minimales autorisées - il modifie simplement ce que vous avez tapé. Une TextBox peut au moins autoriser les valeurs non valides, ce qui vous permet d'avertir l'utilisateur lorsqu'il soumet le formulaire.

1 votes

Il est également possible d'introduire des valeurs dans une zone de texte en utilisant simplement la souris.

172voto

BFree Points 46421

Et juste parce que c'est toujours plus amusant de faire les choses en une seule ligne...

 private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
    {
        e.Handled = !char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar);
    }

REMARQUE : Cela n'empêche pas un utilisateur de copier/coller dans cette zone de texte. Il ne s'agit pas d'un moyen sûr d'assainir vos données.

0 votes

Ce n'est pas une solution générale car elle ne fonctionne que pour les entiers. J'ai eu à implémenter une telle chose récemment et j'ai fini par essayer d'analyser la chaîne résultante en nombre et de n'autoriser l'entrée que si l'analyse a réussi.

1 votes

Cela peut ne pas fonctionner lorsque plusieurs méthodes gèrent KeyPress dans la même zone de texte. Un événement peut définir e.Handled à vrai, et ensuite un autre pourrait le remettre à faux. En général, il est préférable d'utiliser if (...) e.Handled = true;

2 votes

Vous pouvez désactiver la propriété ShortcutsEnabled pour empêcher le copier-coller par le clavier ou le menu.

58voto

Anthony D Points 2856

D'après le contexte et les balises que vous avez utilisées, je suppose que vous écrivez une application .NET C#. Dans ce cas, vous pouvez vous abonner à l'événement de changement de texte et valider chaque frappe de touche.

    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        if (System.Text.RegularExpressions.Regex.IsMatch("[^0-9]", textBox1.Text))
        {
            MessageBox.Show("Please enter only numbers.");
            textBox1.Text.Remove(textBox1.Text.Length - 1);
        }
    }

29 votes

Cela ne va-t-il pas donner un effet très bizarre si vous tapez au milieu d'un nombre ?

5 votes

Et aussi il devrait l'être : textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 1);

3 votes

Et si le premier caractère n'est pas un chiffre... la soustraction de 1 dans ce cas n'entraînerait-elle pas une erreur ? ....

38voto

Simon Mourier Points 49585

Voici un simple contrôle autonome Winforms personnalisé, dérivé de la TextBox standard, qui ne permet que la saisie de System.Int32 (il pourrait être facilement adapté pour d'autres types tels que System.Int64, etc.) Il supporte les opérations de copier/coller et les nombres négatifs :

public class Int32TextBox : TextBox
{
    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        base.OnKeyPress(e);

        NumberFormatInfo fi = CultureInfo.CurrentCulture.NumberFormat;

        string c = e.KeyChar.ToString();
        if (char.IsDigit(c, 0))
            return;

        if ((SelectionStart == 0) && (c.Equals(fi.NegativeSign)))
            return;

        // copy/paste
        if ((((int)e.KeyChar == 22) || ((int)e.KeyChar == 3))
            && ((ModifierKeys & Keys.Control) == Keys.Control))
            return;

        if (e.KeyChar == '\b')
            return;

        e.Handled = true;
    }

    protected override void WndProc(ref System.Windows.Forms.Message m)
    {
        const int WM_PASTE = 0x0302;
        if (m.Msg == WM_PASTE)
        {
            string text = Clipboard.GetText();
            if (string.IsNullOrEmpty(text))
                return;

            if ((text.IndexOf('+') >= 0) && (SelectionStart != 0))
                return;

            int i;
            if (!int.TryParse(text, out i)) // change this for other integer types
                return;

            if ((i < 0) && (SelectionStart != 0))
                return;
        }
        base.WndProc(ref m);
    }

0 votes

C'est génial, joli et simple, facile à utiliser, et traite les tentatives de saisie inhabituelles. Merci !

1 votes

Remarque sur la version 2017, lorsqu'il y a une valeur, par exemple 1, et que vous appuyez sur le retour arrière, elle est ignorée, alors que si vous avez 120 et que vous appuyez trois fois sur le retour arrière, il ne reste que 1.

1 votes

Votre ValidatingTextbox est de loin l'une des meilleures implémentations que j'ai vues depuis un moment. Simple et efficace. Merci !

25voto

TomXP411 Points 101

C'est exactement pour cela que les événements Validated/Validating ont été conçus.

Voici l'article de MSDN sur le sujet : http://msdn.microsoft.com/en-us/library/system.Windows.forms.control.validating.aspx

La version TL;DR : vérifiez la propriété .Text dans l'événement de validation et définissez les paramètres suivants e.Cancel=True lorsque les données ne sont pas valides.

Lorsque vous définissez e.Cancel=True, l'utilisateur ne peut pas quitter le champ, mais vous devez lui indiquer que quelque chose ne va pas. Je change la couleur de fond de la boîte en rouge clair pour indiquer un problème. Veillez à la remettre à SystemColors.Window lorsque Validating est appelé avec une bonne valeur.

2 votes

+1 pour la mention d'une approche très API-idiomatique. Je suis relativement nouveau dans le domaine des formulaires Windows, et c'est une véritable jungle de fonctionnalités et de documents MSDN, alors je vous remercie également de m'avoir indiqué les documents spécifiques suivants Validating . <nitpick> L'OP mentionne que l'idéal est de rejeter/indication immédiate d'un caractère invalidant, mais Validating semble exiger que le focus soit déplacé vers un autre formulaire/contrôle avant qu'il ne prenne effet. </nitpick> Il s'agit néanmoins d'une excellente approche qui mérite d'être considérée dans le cas plus général.

0 votes

Il s'agit d'une excellente solution car une mise en œuvre minimale est requise. Il convient de noter que l'événement Validating ne se produit que lorsque le contrôle perd le focus. Cependant, il est assez facile d'appeler la même fonction de validation à partir de l'appui sur une touche pour obtenir une validation en direct.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X