How do I make a textbox that only accepts numbers?

后端 未结 30 1627
梦如初夏
梦如初夏 2020-11-21 06:05

I have a windows forms app with a textbox control that I want to only accept integer values. In the past I\'ve done this kind of validation by overloading the KeyPress event

相关标签:
30条回答
  • 2020-11-21 06:54

    This is exactly what the Validated/Validating events were designed for.

    Here's the MSDN article on the topic: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.validating.aspx

    The TL;DR version: check the .Text property in the Validating event and set e.Cancel=True when the data is invalid.

    When you set e.Cancel=True, the user can't leave the field, but you will need to give them some kind of feedback that something's wrong. I change the box's background color to light red to indicate a problem. Make sure to set it back to SystemColors.Window when Validating is called with a good value.

    0 讨论(0)
  • 2020-11-21 06:56

    And just because it's always more fun to do stuff in one line...

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

    NOTE: This DOES NOT prevent a user from Copy / Paste into this textbox. It's not a fail safe way to sanitize your data.

    0 讨论(0)
  • 2020-11-21 06:56

    This might be useful. It allows "real" numeric values, including proper decimal points and preceding plus or minus signs. Call it from within the related KeyPress event.

           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;
        }
    
    0 讨论(0)
  • 2020-11-21 06:57

    In our webpage with the definition of textbox we can add an onkeypress event for accepting only numbers. It will not show any message but it will prevent you from wrong input. It worked for me, user could not enter anything except number.

    <asp:TextBox runat="server" ID="txtFrom"
         onkeypress="if(isNaN(String.fromCharCode(event.keyCode))) return false;">
    
    0 讨论(0)
  • 2020-11-21 06:57

    It seems like many of the current answers to this question are manually parsing the input text. If you're looking for a specific built-in numeric type (e.g. int or double), why not just delegate the work to that type's TryParse method? For example:

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

    If you want something more generic but still compatible with Visual Studio's Designer:

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

    And finally, if you want something fully generic and don't care about Designer support:

    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;
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-21 06:59

    Simpler answer:

    _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());
    };
    
    0 讨论(0)
提交回复
热议问题