当前位置:  开发笔记 > 编程语言 > 正文

如何制作仅接受数字的文本框?

如何解决《如何制作仅接受数字的文本框?》经验,为你挑选了9个好方法。

我有一个带有文本框控件的Windows窗体应用程序,我只想接受整数值.在过去,我通过重载KeyPress事件并删除不符合规范的字符来完成这种验证.我看过MaskedTextBox控件,但是我想要一个更通用的解决方案,可以使用正则表达式,或者依赖于其他控件的值.

理想情况下,这将表现为按下非数字字符将不产生结果或立即向用户提供关于无效字符的反馈.



1> Matt Hamilto..:

两种选择:

    NumericUpDown改用.NumericUpDown为您做过滤,这很好.当然,它还使用户能够按下键盘上的向上和向下箭头来增加和减少当前值.

    处理适当的键盘事件以防止数字输入以外的任何事件.我在标准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;
        }
    }
    

如果TextBox不允许小数位,则可以删除检查'.'(以及后续检查多个'.').您还可以添加一个检查,以'-'确定TextBox是否应允许负值.

如果要限制用户的数字位数,请使用: textBox1.MaxLength = 2; // this will allow the user to enter only 2 digits


您需要通过替换"."检查来进行全球化.检查CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator.
顺便说一句,这仍然接受非法的ctrl + v输入; 甚至存在于官方NumericUpDown控件中的错误.
这是真的 - 用户总是可以粘贴一些非数字字符.你希望表单验证能够捕获它,因为在某些时候你会想要做一个Int32.TryParse或其他东西.
@HamishGrubijan,IsControl与Control键无关; 它返回char是否为控件char.通过允许控制字符,您不会破坏退格键,删除键或箭头键
NumericUpDown的唯一缺点是,当您输入超出允许值的最大值或最小值时,它不会提供任何反馈 - 它只会更改您键入的内容.TextBox至少可以允许无效值,因此您可以在用户提交表单时发出警告.
我忘了数字上调控制存在.实际上我应该在这里使用而不是文本框.将来,当我有更复杂的验证时,我将使用带有KeyPress事件的处理属性.

2> BFree..:

而且因为在一条线上做东西总是更有趣......

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

注意:这不会阻止用户复制/粘贴到此文本框中.这不是一种清理数据的失败安全方法.


呃.使用正则表达式覆盖它的`TextChanged`事件可以修复复制粘贴;)
哈哈!是! 一班轮!

3> Anthony D..:

我假设您从上下文和您使用的标签编写.NET C#应用程序.在这种情况下,您可以订阅文本更改事件,并验证每个键击.

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


如果你键入一个数字的中间,这不会产生非常奇怪的效果吗?
它也应该是:`textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 1);`
此外,使用TextChanged而不是KeyPress会创建一些递归,因为代码将在Remove方法之后跳转到第二个TextChanged事件.
如果第一个字符本身不是数字...在这种情况下不会减去1会引发错误...
您切换了IsMatch功能的输入和模式参数.输入应该是第一个,然后是模式.http://msdn.microsoft.com/en-us/library/sdx2bds0(v=vs.110).aspx

4> Simon Mourie..:

这是一个简单的独立Winforms自定义控件,源自标准TextBox,只允许System.Int32输入(它可以很容易地适用于其他类型,如System.Int64等).它支持复制/粘贴操作和负数:

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

2017年更新:我的第一个答案有一些问题:

你可以键入比给定类型的整数更长的东西(例如2147483648大于Int32.MaxValue);

更一般地说,没有真正验证所输入的结果 ;

它只处理int32,你必须为每种类型(Int64等)编写特定的TextBox派生控件

所以我提出了另一个更通用的版本,它仍然支持复制/粘贴,+和 - 符号等.

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

    public event EventHandler 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; }
}

对于Int32,您可以从它派生,如下所示:

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

或者没有派生,使用新的TextValidating事件,如下所示:

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

但它的好处是它适用于任何字符串和任何验证例程.



5> TomXP411..:

这正是验证/验证事件的设计目标.

以下是关于该主题的MSDN文章:http://msdn.microsoft.com/en-us/library/system.windows.forms.control.validating.aspx

TL; DR版本:检查Validating事件中的.Text属性,并e.Cancel=True在数据无效时进行设置.

当你设置e.Cancel = True时,用户不能离开该字段,但你需要给他们一些错误的反馈.我将框的背景颜色更改为浅红色以指示问题.确保在SystemColors.Window使用良好值调用Validating时将其重新设置为.



6> Andrew Kenna..:

试试MaskedTextBox.它采用简单的掩码格式,因此您可以将输入限制为数字或日期或其他任何内容.


我特别不想使用MaskedTextBox。它们允许的格式可能非常有限。他们为这种情况工作,但我想做一些更一般的事情。

7> Davit Tvildi..:

您可以使用该TextChanged活动

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



8> Roger Garret..:

这可能很有用.它允许"实际"数值,包括正确的小数点和前面的加号或减号.从相关的KeyPress事件中调用它.

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



9> Fabio Iotti..:

我一直在研究一组组件来完成WinForms中缺少的东西,这里是:Advanced Forms

特别是这是Regex TextBox的类

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

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

    /// A regular expression governing the input allowed in this text field.
    [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);
    }
}

简单地添加类似的东西myNumbericTextBox.RegexString = "^(\\d+|)$";就足够了.

推荐阅读
Life一切安好
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有