Wie erstelle ich ein Textfeld, das nur Zahlen akzeptiert?


582

Ich habe eine Windows Forms-App mit einem Textfeldsteuerelement, das nur ganzzahlige Werte akzeptieren soll. In der Vergangenheit habe ich diese Art der Validierung durchgeführt, indem ich das KeyPress-Ereignis überladen und nur Zeichen entfernt habe, die nicht der Spezifikation entsprachen. Ich habe mir das MaskedTextBox-Steuerelement angesehen, möchte aber eine allgemeinere Lösung, die möglicherweise mit einem regulären Ausdruck funktioniert oder von den Werten anderer Steuerelemente abhängt.

Im Idealfall würde sich dies so verhalten, dass das Drücken eines nicht numerischen Zeichens entweder kein Ergebnis liefert oder dem Benutzer sofort eine Rückmeldung über das ungültige Zeichen gibt.


11
Zahlen oder Ziffern? großer Unterschied: Auch ganze Zahlen können negativ werden
Joel Coehoorn

8
Die Frage war für Zahlen gedacht, einschließlich der gesamten Menge rationaler Zahlen.
Mykroft

Antworten:


797

Zwei Optionen:

  1. Verwenden Sie NumericUpDownstattdessen ein. NumericUpDown übernimmt die Filterung für Sie, was sehr schön ist. Natürlich können Ihre Benutzer auch die Aufwärts- und Abwärtspfeile auf der Tastatur drücken, um den aktuellen Wert zu erhöhen und zu verringern.

  2. Behandeln Sie die entsprechenden Tastaturereignisse, um alles andere als numerische Eingaben zu verhindern. Ich hatte Erfolg mit diesen beiden Ereignishandlern auf einer Standard-TextBox:

    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;
        }
    }
    

Sie können die Prüfung für '.'(und die nachfolgende Prüfung für mehr als eine '.') entfernen, wenn Ihre TextBox keine Dezimalstellen zulassen soll. Sie können auch prüfen, '-'ob Ihre TextBox negative Werte zulassen soll.

Wenn Sie den Benutzer auf die Anzahl der Ziffern beschränken möchten, verwenden Sie: textBox1.MaxLength = 2; // this will allow the user to enter only 2 digits


5
Der einzige Nachteil von NumericUpDown ist, dass es keine Rückmeldung gibt, wenn Sie einen Wert außerhalb der maximal oder minimal zulässigen Werte eingeben. Es ändert lediglich die Eingabe. Eine TextBox kann zumindest ungültige Werte zulassen, sodass Sie den Benutzer warnen können, wenn er das Formular sendet.
Matt Hamilton

7
Das stimmt - der Benutzer kann immer einige nicht numerische Zeichen einfügen. Sie würden hoffen, dass die Formularvalidierung dies jedoch erfasst, da Sie irgendwann eine Int32.TryParse oder etwas anderes ausführen möchten.
Matt Hamilton

52
Sie müssen zusätzliche Anstrengungen unternehmen, um dies zu globalisieren, indem Sie die Überprüfungen für '.' Ersetzen. mit Überprüfungen von CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator.
Jeff Yates

6
@HamishGrubijan, IsControl hat nichts mit der Steuertaste zu tun. Es wird zurückgegeben, ob ein Zeichen ein Steuerzeichen ist oder nicht. Indem Sie Steuerzeichen zulassen, brechen Sie keine Dinge wie Rücktaste, Löschen oder die Pfeiltasten
Thomas Levesque

13
Dies akzeptiert übrigens immer noch illegale Strg + V-Eingaben; Ein Fehler, der sogar im offiziellen NumericUpDown-Steuerelement vorhanden ist.
Nyerguds

149

Und nur weil es immer mehr Spaß macht, Dinge in einer Zeile zu erledigen ...

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

HINWEIS: Dies verhindert NICHT, dass ein Benutzer in dieses Textfeld kopiert / einfügt. Es ist kein ausfallsicherer Weg, Ihre Daten zu bereinigen.


Dies ist keine allgemeine Lösung, da sie nur für Interger funktioniert. Ich musste so etwas kürzlich implementieren und habe am Ende versucht, die resultierende Zeichenfolge auf Zahl zu analysieren und die Eingabe nur zuzulassen, wenn die Analyse erfolgreich war
grzegorz_p

1
Dies funktioniert möglicherweise nicht, wenn mehrere Methoden KeyPressEreignisse aus demselben Textfeld verarbeiten. Ein Ereignis könnte e.Handledauf true gesetzt werden, und ein anderes könnte es auf false zurücksetzen. Im Allgemeinen ist es besser zu verwendenif (...) e.Handled = true;
Nathaniel Jones

2
Sie können die ShortcutsEnabled-Eigenschaft deaktivieren, um das Einfügen von Kopien über Tastatur oder Menü zu verhindern
Ahmad

3
HAHA! Ja! Ein Liner!
Jamie L.

3
Eh. Ein TextChangedEreignis, das mit einem
regulären Ausdruck darüber

51

Ich gehe vom Kontext und den von Ihnen verwendeten Tags davon aus, dass Sie eine .NET C # -App schreiben. In diesem Fall können Sie das Ereignis "Text geändert" abonnieren und jeden Tastendruck überprüfen.

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

22
Wird das nicht einen sehr seltsamen Effekt haben, wenn Sie in die Mitte einer Zahl tippen?
Colin Pickard

5
und es sollte auch sein:textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 1);
Pieniadz

3
Was ist, wenn das erste Zeichen selbst keine Ziffer ist
? Wenn

6
Wenn Sie TextChanged anstelle von KeyPress verwenden, entsteht eine gewisse Rekursion, da der Code nach der Remove-Methode in ein zweites TextChanged-Ereignis springt.
WEFX

2
Sie haben die Eingangs- und Musterparameter für Ihre IsMatch-Funktion umgeschaltet. Die Eingabe sollte zuerst erfolgen, dann das Muster. msdn.microsoft.com/en-us/library/sdx2bds0(v=vs.110).aspx
Mibou

36

Hier ist ein einfaches eigenständiges benutzerdefiniertes Winforms-Steuerelement, das von der Standard-TextBox abgeleitet ist und nur System.Int32-Eingaben zulässt (es kann problemlos für andere Typen wie System.Int64 usw. angepasst werden). Es unterstützt Kopier- / Einfügevorgänge und negative Zahlen:

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);
    }

Update 2017 : Meine erste Antwort hat einige Probleme:

  • Sie können etwas eingeben, das länger als eine Ganzzahl eines bestimmten Typs ist (z. B. 2147483648 ist größer als Int32.MaxValue).
  • Im Allgemeinen gibt es keine wirkliche Bestätigung des Ergebnisses dessen, was eingegeben wurde.
  • Es wird nur int32 verarbeitet. Sie müssen für jeden Typ (Int64 usw.) ein spezifisches TextBox-abgeleitetes Steuerelement schreiben.

Also habe ich mir eine andere Version ausgedacht, die allgemeiner ist und weiterhin Kopieren / Einfügen, + und - Zeichen usw. unterstützt.

public class ValidatingTextBox : TextBox
{
    private string _validText;
    private int _selectionStart;
    private int _selectionEnd;
    private bool _dontProcessMessages;

    public event EventHandler<TextValidatingEventArgs> TextValidating;

    protected virtual void OnTextValidating(object sender, TextValidatingEventArgs e) => TextValidating?.Invoke(sender, e);

    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        if (_dontProcessMessages)
            return;

        const int WM_KEYDOWN = 0x100;
        const int WM_ENTERIDLE = 0x121;
        const int VK_DELETE = 0x2e;

        bool delete = m.Msg == WM_KEYDOWN && (int)m.WParam == VK_DELETE;
        if ((m.Msg == WM_KEYDOWN && !delete) || m.Msg == WM_ENTERIDLE)
        {
            DontProcessMessage(() =>
            {
                _validText = Text;
                _selectionStart = SelectionStart;
                _selectionEnd = SelectionLength;
            });
        }

        const int WM_CHAR = 0x102;
        const int WM_PASTE = 0x302;
        if (m.Msg == WM_CHAR || m.Msg == WM_PASTE || delete)
        {
            string newText = null;
            DontProcessMessage(() =>
            {
                newText = Text;
            });

            var e = new TextValidatingEventArgs(newText);
            OnTextValidating(this, e);
            if (e.Cancel)
            {
                DontProcessMessage(() =>
                {
                    Text = _validText;
                    SelectionStart = _selectionStart;
                    SelectionLength = _selectionEnd;
                });
            }
        }
    }

    private void DontProcessMessage(Action action)
    {
        _dontProcessMessages = true;
        try
        {
            action();
        }
        finally
        {
            _dontProcessMessages = false;
        }
    }
}

public class TextValidatingEventArgs : CancelEventArgs
{
    public TextValidatingEventArgs(string newText) => NewText = newText;
    public string NewText { get; }
}

Für Int32 können Sie entweder Folgendes ableiten:

public class Int32TextBox : ValidatingTextBox
{
    protected override void OnTextValidating(object sender, TextValidatingEventArgs e)
    {
        e.Cancel = !int.TryParse(e.NewText, out int i);
    }
}

Verwenden Sie das neue TextValidating-Ereignis ohne Ableitung wie folgt:

var vtb = new ValidatingTextBox();
...
vtb.TextValidating += (sender, e) => e.Cancel = !int.TryParse(e.NewText, out int i);

Aber das Schöne ist, dass es mit jeder Zeichenfolge und jeder Validierungsroutine funktioniert.


Dies ist großartig, nett und einfach, leicht zu bedienen und behandelt ungewöhnliche Eingabeversuche. Vielen Dank!
WiredEarp

1
Hinweis zur Version 2017: Wenn es einen Wert gibt, z. B. 1, und Sie die Rücktaste drücken, wird dieser ignoriert. Wenn Sie 120 sagen und dreimal die
Karen Payne

1
Ihre ValidatingTextbox ist bei weitem eine der besten Implementierungen, die ich seit einiger Zeit gesehen habe. Einfach und effektiv. Vielen Dank!
Samuel

19

Genau dafür wurden die Validated / Validating-Ereignisse entwickelt.

Hier ist der MSDN-Artikel zum Thema: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.validating.aspx

Die TL; DR-Version: Überprüfen Sie die .Text-Eigenschaft im Validating-Ereignis und legen Sie fest, e.Cancel=Truewann die Daten ungültig sind.

Wenn Sie e.Cancel = True setzen, kann der Benutzer das Feld nicht verlassen, aber Sie müssen ihm eine Art Feedback geben, dass etwas nicht stimmt. Ich ändere die Hintergrundfarbe der Box auf hellrot, um auf ein Problem hinzuweisen. Stellen Sie sicher, dass Sie es auf SystemColors.Windowzurücksetzen , wenn Validating mit einem guten Wert aufgerufen wird.


1
+1 für die Erwähnung eines sehr API-idiomatischen Ansatzes. Ich bin relativ neu in Windows Forms und es ist ein Dschungel von Funktionen und MSDN-Dokumenten. Vielen Dank auch für den speziellen Dokumentzeiger auf Validating. <nitpick>Das OP erwähnt, dass das sofortige Nichtzulassen / Anzeigen eines ungültig machenden Zeichens ideal ist, aber Validatinganscheinend erfordert, dass der Fokus auf eine andere Form / Steuerung verschoben wird, bevor er wirksam wird. </nitpick>Trotzdem ist dies ein großartiger Ansatz und im allgemeineren Fall immer eine Überlegung wert.
William

13

Versuchen Sie es mit einer MaskedTextBox . Es wird ein einfaches Maskenformat verwendet, sodass Sie die Eingabe auf Zahlen oder Datumsangaben oder was auch immer beschränken können.


2
Ich möchte ausdrücklich keine MaskedTextBox verwenden. Die Formate, die sie zulassen, können sehr einschränkend sein. Sie arbeiten für diesen Fall, aber ich möchte etwas allgemeineres tun.
Mykroft

12

Sie können das TextChangedEreignis verwenden

private void textBox_BiggerThan_TextChanged(object sender, EventArgs e)
{
    long a;
    if (! long.TryParse(textBox_BiggerThan.Text, out a))
    {
        // If not int clear textbox text or Undo() last operation
        textBox_LessThan.Clear();
    }
}

Sieht so aus, als ob es gut funktionieren sollte, wenn Sie es verwenden Undo(), aber es führt zu einem StackOverflowException.
Drew Chapin

Es sieht so aus, als ob die Eigenschaft TextChanged Teil der Routine ist, die Sie rückgängig machen möchten (). Ich habe Variable für das gesamte Fenster und ich benutze public int txtBoxValue, und wenn tryParse nicht funktioniert, setze ich Text in txtBox vontxtBox.Text = txtBoxValue.ToString();
L. Zeda

8

Dies könnte nützlich sein. Es erlaubt "reelle" numerische Werte, einschließlich korrekter Dezimalstellen und vorhergehender Plus- oder Minuszeichen. Rufen Sie es innerhalb des zugehörigen KeyPress-Ereignisses auf.

       private bool IsOKForDecimalTextBox(char theCharacter, TextBox theTextBox)
    {
        // Only allow control characters, digits, plus and minus signs.
        // Only allow ONE plus sign.
        // Only allow ONE minus sign.
        // Only allow the plus or minus sign as the FIRST character.
        // Only allow ONE decimal point.
        // Do NOT allow decimal point or digits BEFORE any plus or minus sign.

        if (
            !char.IsControl(theCharacter)
            && !char.IsDigit(theCharacter)
            && (theCharacter != '.')
            && (theCharacter != '-')
            && (theCharacter != '+')
        )
        {
            // Then it is NOT a character we want allowed in the text box.
            return false;
        }



        // Only allow one decimal point.
        if (theCharacter == '.'
            && theTextBox.Text.IndexOf('.') > -1)
        {
            // Then there is already a decimal point in the text box.
            return false;
        }

        // Only allow one minus sign.
        if (theCharacter == '-'
            && theTextBox.Text.IndexOf('-') > -1)
        {
            // Then there is already a minus sign in the text box.
            return false;
        }

        // Only allow one plus sign.
        if (theCharacter == '+'
            && theTextBox.Text.IndexOf('+') > -1)
        {
            // Then there is already a plus sign in the text box.
            return false;
        }

        // Only allow one plus sign OR minus sign, but not both.
        if (
            (
                (theCharacter == '-')
                || (theCharacter == '+')
            )
            && 
            (
                (theTextBox.Text.IndexOf('-') > -1)
                ||
                (theTextBox.Text.IndexOf('+') > -1)
            )
            )
        {
            // Then the user is trying to enter a plus or minus sign and
            // there is ALREADY a plus or minus sign in the text box.
            return false;
        }

        // Only allow a minus or plus sign at the first character position.
        if (
            (
                (theCharacter == '-')
                || (theCharacter == '+')
            )
            && theTextBox.SelectionStart != 0
            )
        {
            // Then the user is trying to enter a minus or plus sign at some position 
            // OTHER than the first character position in the text box.
            return false;
        }

        // Only allow digits and decimal point AFTER any existing plus or minus sign
        if  (
                (
                    // Is digit or decimal point
                    char.IsDigit(theCharacter)
                    ||
                    (theCharacter == '.')
                )
                &&
                (
                    // A plus or minus sign EXISTS
                    (theTextBox.Text.IndexOf('-') > -1)
                    ||
                    (theTextBox.Text.IndexOf('+') > -1)
                )
                &&
                    // Attempting to put the character at the beginning of the field.
                    theTextBox.SelectionStart == 0
            )
        {
            // Then the user is trying to enter a digit or decimal point in front of a minus or plus sign.
            return false;
        }

        // Otherwise the character is perfectly fine for a decimal value and the character
        // may indeed be placed at the current insertion position.
        return true;
    }

6

Ich habe an einer Sammlung von Komponenten gearbeitet, um fehlende Inhalte in WinForms zu vervollständigen. Hier ist es: Erweiterte Formulare

Dies ist insbesondere die Klasse für eine Regex TextBox

/// <summary>Represents a Windows text box control that only allows input that matches a regular expression.</summary>
public class RegexTextBox : TextBox
{
    [NonSerialized]
    string lastText;

    /// <summary>A regular expression governing the input allowed in this text field.</summary>
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public virtual Regex Regex { get; set; }

    /// <summary>A regular expression governing the input allowed in this text field.</summary>
    [DefaultValue(null)]
    [Category("Behavior")]
    [Description("Sets the regular expression governing the input allowed for this control.")]
    public virtual string RegexString {
        get {
            return Regex == null ? string.Empty : Regex.ToString();
        }
        set {
            if (string.IsNullOrEmpty(value))
                Regex = null;
            else
                Regex = new Regex(value);
        }
    }

    protected override void OnTextChanged(EventArgs e) {
        if (Regex != null && !Regex.IsMatch(Text)) {
            int pos = SelectionStart - Text.Length + (lastText ?? string.Empty).Length;
            Text = lastText;
            SelectionStart = Math.Max(0, pos);
        }

        lastText = Text;

        base.OnTextChanged(e);
    }
}

Es myNumbericTextBox.RegexString = "^(\\d+|)$";sollte ausreichen, einfach so etwas hinzuzufügen .


5

Verwenden Sie einfach ein NumericUpDownSteuerelement und stellen Sie die Sichtbarkeit dieser hässlichen Auf-Ab-Schaltflächen auf ein false.

numericUpDown1.Controls[0].Visible = false;

NumericUpDown ist eigentlich eine Sammlung von Steuerelementen, die ein 'Drehfeld' (Auf-Ab-Schaltflächen), ein Textfeld und einen Code enthalten, um alles zu validieren und durcheinander zu bringen.

Markierung:

YourNumericUpDown.Controls[0].visible = false 

blendet die Schaltflächen aus, während der zugrunde liegende Code aktiv bleibt.

Obwohl dies keine offensichtliche Lösung ist, ist es einfach und effektiv. .Controls[1]würde den Textfeldteil ausblenden, wenn Sie das stattdessen tun wollten.


Die akzeptierte Antwort enthielt keine Informationen zum Entfernen der Auf-Ab-Schaltflächen. Dies ist nicht offensichtlich, da keine vom Menschen lesbaren Schnittstellen zum Aktivieren oder Deaktivieren vorhanden sind. NumericUpDown ist eigentlich eine Sammlung von Steuerelementen, die ein Textfeld und ein "Drehfeld" (Auf-Ab-Schaltflächen) sowie eine Validierung der Eingabe von Code enthalten.
user2163234

4

Ich habe auf CodePlex etwas dafür gemacht .

Es funktioniert durch Abfangen des TextChanged-Ereignisses. Wenn das Ergebnis eine gute Zahl ist, wird es gespeichert. Wenn etwas nicht stimmt, wird der letzte gute Wert wiederhergestellt. Die Quelle ist etwas zu groß, um hier veröffentlicht zu werden, aber hier ist ein Link zu der Klasse , die den Kern dieser Logik behandelt.


4

Verwenden Sie einfach diesen Code im Textfeld:

private void textBox1_TextChanged(object sender, EventArgs e)
{

    double parsedValue;

    if (!double.TryParse(textBox1.Text, out parsedValue))
    {
        textBox1.Text = "";
    }
}

4

Auf unserer Webseite mit der Definition des Textfelds können wir ein onkeypressEreignis hinzufügen , bei dem nur Zahlen akzeptiert werden. Es wird keine Meldung angezeigt, aber es wird verhindert, dass Sie falsche Eingaben machen. Es hat bei mir funktioniert, der Benutzer konnte nur die Nummer eingeben.

<asp:TextBox runat="server" ID="txtFrom"
     onkeypress="if(isNaN(String.fromCharCode(event.keyCode))) return false;">


2

Ich würde es im KeyDown-Ereignis behandeln.

void TextBox_KeyDown(object sender, KeyEventArgs e)
        {
            char c = Convert.ToChar(e.PlatformKeyCode);
            if (!char.IsDigit(c))
            {
                e.Handled = true;
            }
        }

2
Was ist mit Schlüsseln wie "Rücktaste", "Löschen", "Pfeiltaste-Links", "Pfeiltaste-Rechts", Kopieren und Einfügen, von Numpad eingegebene Ziffern (sie werden als! Ziffer gehandelt)
user799821

Fügen Sie einfach ein paar weitere Tests wie diesen hinzu: if (! Char.IsDigit (c) && c! = (Char) Keys.Back)
dnennis

2
private void txt3_KeyPress(object sender, KeyPressEventArgs e)
{
    for (int h = 58; h <= 127; h++)
    {
        if (e.KeyChar == h)             //58 to 127 is alphabets tat will be         blocked
        {
            e.Handled = true;
        }
    }
    for(int k=32;k<=47;k++)
    {
        if (e.KeyChar == k)              //32 to 47 are special characters tat will 
        {                                  be blocked
            e.Handled = true;
        }
    }
}

versuchen Sie dies ist sehr einfach


2

Sehen Sie sich die Eingabebehandlung in WinForm an

Ich habe meine Lösung veröffentlicht, die die ProcessCmdKey- und OnKeyPress-Ereignisse im Textfeld verwendet. Die Kommentare zeigen Ihnen, wie Sie mit einem Regex den Tastendruck überprüfen und entsprechend blockieren / zulassen.


2

Hallo, Sie können so etwas im textveränderten Ereignis des Textfelds tun.

Hier ist eine Demo

    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        string actualdata = string.Empty;
        char[] entereddata = textBox1.Text.ToCharArray();
        foreach (char aChar in entereddata.AsEnumerable())
        {
            if (Char.IsDigit(aChar))
            {
                actualdata = actualdata + aChar;
                // MessageBox.Show(aChar.ToString());
            }
            else
            {
                MessageBox.Show(aChar + " is not numeric");
                actualdata.Replace(aChar, ' ');
                actualdata.Trim();
            }
        }
        textBox1.Text = actualdata;
    }

Danke, es ist sehr nützlich.
Kiran RS

2

Es scheint, dass viele der aktuellen Antworten auf diese Frage den Eingabetext manuell analysieren. Wenn Sie nach einem bestimmten integrierten numerischen Typ suchen (z. B. intoder double), können Sie die Arbeit einfach an die TryParseMethode dieses Typs delegieren . Zum Beispiel:

public class IntTextBox : TextBox
{
    string PreviousText = "";
    int BackingResult;

    public IntTextBox()
    {
        TextChanged += IntTextBox_TextChanged;
    }

    public bool HasResult { get; private set; }

    public int Result
    {
        get
        {
            return HasResult ? BackingResult : default(int);
        }
    }

    void IntTextBox_TextChanged(object sender, EventArgs e)
    {
        HasResult = int.TryParse(Text, out BackingResult);

        if (HasResult || string.IsNullOrEmpty(Text))
        {
            // Commit
            PreviousText = Text;
        }
        else
        {
            // Revert
            var changeOffset = Text.Length - PreviousText.Length;
            var previousSelectionStart =
                Math.Max(0, SelectionStart - changeOffset);

            Text = PreviousText;
            SelectionStart = previousSelectionStart;
        }
    }
}

Wenn Sie etwas allgemeineres möchten, aber dennoch mit dem Designer von Visual Studio kompatibel sind:

public class ParsableTextBox : TextBox
{
    TryParser BackingTryParse;
    string PreviousText = "";
    object BackingResult;

    public ParsableTextBox()
        : this(null)
    {
    }

    public ParsableTextBox(TryParser tryParse)
    {
        TryParse = tryParse;

        TextChanged += ParsableTextBox_TextChanged;
    }

    public delegate bool TryParser(string text, out object result);

    public TryParser TryParse
    {
        set
        {
            Enabled = !(ReadOnly = value == null);

            BackingTryParse = value;
        }
    }

    public bool HasResult { get; private set; }

    public object Result
    {
        get
        {
            return GetResult<object>();
        }
    }

    public T GetResult<T>()
    {
        return HasResult ? (T)BackingResult : default(T);
    }

    void ParsableTextBox_TextChanged(object sender, EventArgs e)
    {
        if (BackingTryParse != null)
        {
            HasResult = BackingTryParse(Text, out BackingResult);
        }

        if (HasResult || string.IsNullOrEmpty(Text))
        {
            // Commit
            PreviousText = Text;
        }
        else
        {
            // Revert
            var changeOffset = Text.Length - PreviousText.Length;
            var previousSelectionStart =
                Math.Max(0, SelectionStart - changeOffset);

            Text = PreviousText;
            SelectionStart = previousSelectionStart;
        }
    }
}

Und schließlich, wenn Sie etwas generisches möchten und sich nicht für die Designer-Unterstützung interessieren:

public class ParsableTextBox<T> : TextBox
{
    TryParser BackingTryParse;
    string PreviousText;
    T BackingResult;

    public ParsableTextBox()
        : this(null)
    {
    }

    public ParsableTextBox(TryParser tryParse)
    {
        TryParse = tryParse;

        TextChanged += ParsableTextBox_TextChanged;
    }

    public delegate bool TryParser(string text, out T result);

    public TryParser TryParse
    {
        set
        {
            Enabled = !(ReadOnly = value == null);

            BackingTryParse = value;
        }
    }

    public bool HasResult { get; private set; }

    public T Result
    {
        get
        {
            return HasResult ? BackingResult : default(T);
        }
    }

    void ParsableTextBox_TextChanged(object sender, EventArgs e)
    {
        if (BackingTryParse != null)
        {
            HasResult = BackingTryParse(Text, out BackingResult);
        }

        if (HasResult || string.IsNullOrEmpty(Text))
        {
            // Commit
            PreviousText = Text;
        }
        else
        {
            // Revert
            var changeOffset = Text.Length - PreviousText.Length;
            var previousSelectionStart =
                Math.Max(0, SelectionStart - changeOffset);

            Text = PreviousText;
            SelectionStart = previousSelectionStart;
        }
    }
}

2

Sowohl Ganzzahlen als auch Gleitkommazahlen müssen akzeptiert werden, einschließlich der negativen Zahlen.

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    // Text
    string text = ((Control) sender).Text;

    // Is Negative Number?
    if (e.KeyChar == '-' && text.Length == 0)
    {
        e.Handled = false;
        return;
    }

    // Is Float Number?
    if (e.KeyChar == '.' && text.Length > 0 && !text.Contains("."))
    {
        e.Handled = false;
        return;
    }

    // Is Digit?
    e.Handled = (!char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar));
}

2

Das ist mein Ansatz:

  1. mit linq (einfach zu ändernder Filter)
  2. Proof-Code kopieren / einfügen
  3. behält die Caret-Position bei, wenn Sie ein verbotenes Zeichen drücken
  4. akzeptiert linke Nullen
  5. und beliebige Größen

    private void numeroCuenta_TextChanged(object sender, EventArgs e)
    {
        string org = numeroCuenta.Text;
        string formated = string.Concat(org.Where(c => (c >= '0' && c <= '9')));
        if (formated != org)
        {
            int s = numeroCuenta.SelectionStart;
            if (s > 0 && formated.Length > s && org[s - 1] != formated[s - 1]) s--;
            numeroCuenta.Text = formated;
            numeroCuenta.SelectionStart = s;
        }
    }

2

Mit dem in Fabio Iottis Antwort beschriebenen Ansatz habe ich eine allgemeinere Lösung geschaffen:

public abstract class ValidatedTextBox : TextBox {
    private string m_lastText = string.Empty;
    protected abstract bool IsValid(string text);
    protected sealed override void OnTextChanged(EventArgs e) {
        if (!IsValid(Text)) {
            var pos = SelectionStart - Text.Length + m_lastText.Length;
            Text = m_lastText;
            SelectionStart = Math.Max(0, pos);
        }
        m_lastText = Text;
        base.OnTextChanged(e);
    }
}

"ValidatedTextBox", die alle nicht trivialen Validierungsverhalten enthält. Sie müssen nur noch von dieser Klasse erben und die "IsValid" -Methode mit der erforderlichen Validierungslogik überschreiben. Mit dieser Klasse ist es beispielsweise möglich, "RegexedTextBox" zu erstellen, die nur Zeichenfolgen akzeptiert, die einem bestimmten regulären Ausdruck entsprechen:

public abstract class RegexedTextBox : ValidatedTextBox {
    private readonly Regex m_regex;
    protected RegexedTextBox(string regExpString) {
        m_regex = new Regex(regExpString);
    }
    protected override bool IsValid(string text) {
        return m_regex.IsMatch(Text);
    }
}

Danach können wir, indem wir von der Klasse "RegexedTextBox" erben, einfach die Steuerelemente "PositiveNumberTextBox" und "PositiveFloatingPointNumberTextBox" erstellen:

public sealed class PositiveNumberTextBox : RegexedTextBox {
    public PositiveNumberTextBox() : base(@"^\d*$") { }
}

public sealed class PositiveFloatingPointNumberTextBox : RegexedTextBox {
    public PositiveFloatingPointNumberTextBox()
        : base(@"^(\d+\" + CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator + @")?\d*$") { }
}

1

Es tut mir leid, die Toten zu wecken, aber ich dachte, jemand könnte dies als zukünftige Referenz nützlich finden.

So gehe ich damit um. Es verarbeitet Gleitkommazahlen, kann jedoch leicht für Ganzzahlen geändert werden.

Grundsätzlich können Sie nur 0 - 9 und drücken .

Sie können nur eine 0 vor dem haben .

Alle anderen Zeichen werden ignoriert und die Cursorposition beibehalten.

    private bool _myTextBoxChanging = false;

    private void myTextBox_TextChanged(object sender, EventArgs e)
    {
        validateText(myTextBox);
    }

    private void validateText(TextBox box)
    {
        // stop multiple changes;
        if (_myTextBoxChanging)
            return;
        _myTextBoxChanging = true;

        string text = box.Text;
        if (text == "")
            return;
        string validText = "";
        bool hasPeriod = false;
        int pos = box.SelectionStart;
        for (int i = 0; i < text.Length; i++ )
        {
            bool badChar = false;
            char s = text[i];
            if (s == '.')
            {
                if (hasPeriod)
                    badChar = true;
                else
                    hasPeriod = true;
            }
            else if (s < '0' || s > '9')
                badChar = true;

            if (!badChar)
                validText += s;
            else
            {
                if (i <= pos)
                    pos--;
            }
        }

        // trim starting 00s
        while (validText.Length >= 2 && validText[0] == '0')
        {
            if (validText[1] != '.')
            {
                validText = validText.Substring(1);
                if (pos < 2)
                    pos--;
            }
            else
                break;
        }

        if (pos > validText.Length)
            pos = validText.Length;
        box.Text = validText;
        box.SelectionStart = pos;
        _myTextBoxChanging = false;
    }

Hier ist eine schnell modifizierte int-Version:

    private void validateText(TextBox box)
    {
        // stop multiple changes;
        if (_myTextBoxChanging)
            return;
        _myTextBoxChanging = true;

        string text = box.Text;
        if (text == "")
            return;
        string validText = "";
        int pos = box.SelectionStart;
        for (int i = 0; i < text.Length; i++ )
        {
            char s = text[i];
            if (s < '0' || s > '9')
            {
                if (i <= pos)
                    pos--;
            }
            else
                validText += s;
        }

        // trim starting 00s 
        while (validText.Length >= 2 && validText.StartsWith("00")) 
        { 
            validText = validText.Substring(1); 
            if (pos < 2) 
                pos--; 
        } 

        if (pos > validText.Length)
            pos = validText.Length;
        box.Text = validText;
        box.SelectionStart = pos;
        _myTextBoxChanging = false;
    }

2
Diese Lösung erfindet das Rad mit Einschränkungen neu. Lokalisierung zum Beispiel.
Julien Guertault

1

Dieser arbeitet mit Kopieren und Einfügen, Ziehen und Ablegen, Drücken der Taste, verhindert Überlauf und ist ziemlich einfach

public partial class IntegerBox : TextBox 
{
    public IntegerBox()
    {
        InitializeComponent();
        this.Text = 0.ToString();
    }

    protected override void OnPaint(PaintEventArgs pe)
    {
        base.OnPaint(pe);
    }

    private String originalValue = 0.ToString();

    private void Integerbox_KeyPress(object sender, KeyPressEventArgs e)
    {
        originalValue = this.Text;
    }

    private void Integerbox_TextChanged(object sender, EventArgs e)
    {
        try
        {
            if(String.IsNullOrWhiteSpace(this.Text))
            {
                this.Text = 0.ToString();
            }
            this.Text = Convert.ToInt64(this.Text.Trim()).ToString();
        }
        catch (System.OverflowException)
        {
            MessageBox.Show("Value entered is to large max value: " + Int64.MaxValue.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            this.Text = originalValue;
        }
        catch (System.FormatException)
        {                
            this.Text = originalValue;
        }
        catch (System.Exception ex)
        {
            this.Text = originalValue;
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK , MessageBoxIcon.Error);
        }
    }       
}

1

Vergessen Sie nicht, dass ein Benutzer einen ungültigen Text in a einfügen kann TextBox.

Wenn Sie dies einschränken möchten, befolgen Sie den folgenden Code:

private void ultraTextEditor1_TextChanged(object sender, EventArgs e)
{
    string append="";
    foreach (char c in ultraTextEditor1.Text)
    {
        if ((!Char.IsNumber(c)) && (c != Convert.ToChar(Keys.Back)))
        {

        }
        else
        {
            append += c;
        }
    }

    ultraTextEditor1.Text = append;
}   

1

Ich suchte auch nach dem besten Weg, um nur Zahlen im Textfeld zu überprüfen, und das Problem mit dem Tastendruck war, dass das Einfügen durch Kopieren per Rechtsklick oder Zwischenablage nicht unterstützt wird. Daher wurde dieser Code entwickelt, der überprüft, wann der Cursor das Textfeld verlässt und auch nach prüft leeres Feld. (angepasste Version von Newguy)

private void txtFirstValue_MouseLeave(object sender, EventArgs e)
{
    int num;
    bool isNum = int.TryParse(txtFirstValue.Text.Trim(), out num);

    if (!isNum && txtFirstValue.Text != String.Empty)
    {
        MessageBox.Show("The First Value You Entered Is Not a Number, Please Try Again", "Invalid Value Detected", MessageBoxButtons.OK, MessageBoxIcon.Error);
        txtFirstValue.Clear();
    }
}

MouseLeave scheint eine wirklich schlechte Wahl für eine Veranstaltung zu sein.
LarsTech

@LarsTech Was ich für textgeändert hielt, kann sogar zu einer Fehlermeldung führen, selbst wenn der Benutzer einen Fehler erkennt und versucht, ihn zu beheben, sodass ich dachte, ich würde besser arbeiten. Was ist Ihrer Meinung nach das beste Ereignis für diesen Fall?
Alston Antony

@AlstonAntony später Kommentar, ich weiß. Aber ein einfaches Klickereignis, das bei Rechtsklick aktiviert wird, würde ausreichen, nicht wahr?
Takarii

0
int Number;
bool isNumber;
isNumber = int32.TryPase(textbox1.text, out Number);

if (!isNumber)
{ 
    (code if not an integer);
}
else
{
    (code if an integer);
}

0

3 Lösung

1)

//Add to the textbox's KeyPress event
//using Regex for number only textBox

private void txtBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (!System.Text.RegularExpressions.Regex.IsMatch(e.KeyChar.ToString(), "\\d+"))
e.Handled = true;
}

2) eine andere Lösung von msdn

// Boolean flag used to determine when a character other than a number is entered.
private bool nonNumberEntered = false;
// Handle the KeyDown event to determine the type of character entered into the     control.
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
// Initialize the flag to false.
nonNumberEntered = false;
// Determine whether the keystroke is a number from the top of the keyboard.
if (e.KeyCode < Keys.D0 || e.KeyCode > Keys.D9)
{
    // Determine whether the keystroke is a number from the keypad.
    if (e.KeyCode < Keys.NumPad0 || e.KeyCode > Keys.NumPad9)
    {
        // Determine whether the keystroke is a backspace.
        if (e.KeyCode != Keys.Back)
        {
            // A non-numerical keystroke was pressed.
            // Set the flag to true and evaluate in KeyPress event.
            nonNumberEntered = true;
        }
    }
}

}}

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    if (nonNumberEntered == true)
    {
       MessageBox.Show("Please enter number only..."); 
       e.Handled = true;
    }
}

Quelle http://msdn.microsoft.com/en-us/library/system.windows.forms.control.keypress(v=VS.90).aspx

3) Verwenden der MaskedTextBox: http://msdn.microsoft.com/en-us/library/system.windows.forms.maskedtextbox.aspx


0

Mit einem Klick auf die Schaltfläche können Sie den Text des Textfelds anhand der for-Schleife überprüfen:

char[] c = txtGetCustomerId.Text.ToCharArray();
bool IsDigi = true;

for (int i = 0; i < c.Length; i++)
     {
       if (c[i] < '0' || c[i] > '9')
      { IsDigi = false; }
     }
 if (IsDigi)
    { 
     // do something
    }

0

Einfachere Antwort:

_textBox.TextChanged += delegate(System.Object o, System.EventArgs e)
{
    TextBox _tbox = o as TextBox;
    _tbox.Text = new string(_tbox.Text.Where(c => (char.IsDigit(c)) || (c == '.')).ToArray());
};
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.