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


582

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

理想情况下,这样做是为了使按下非数字字符不会产生任何结果,或者会立即向用户提供有关无效字符的反馈。


11
数字还是数字?最大的不同:即使整数也可以
变为

8
这个问题是针对数字的,包括整个有理数。
Mykroft

Answers:


797

两种选择:

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

  2. 处理适当的键盘事件,以防止除数字输入之外的任何操作。我已经在标准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


5
NumericUpDown的唯一缺点是,当您输入最大或最小允许值之外的值时,它不会提供任何反馈-它只会更改您键入的内容。TextBox至少可以允许无效值,因此您可以在用户提交表单时警告用户。
Matt Hamilton 2009年

7
没错-用户始终可以粘贴一些非数字字符。您希望表单验证能够捕获到该错误,因为在某个时候您将要执行Int32.TryParse或其他操作。
马特·汉密尔顿,

52
您将需要一些额外的工作来通过替换'。'来使它全球化。检查CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator。
Jeff Yates

6
@ HamishGrubijan,IsControl与Control键无关;它返回一个char是否为控制char。通过允许使用控制字符,您不会破坏退格键,删除键或箭头键之类的东西
Thomas Levesque

13
顺便说一句,这仍然接受非法的ctrl + v输入;一个甚至存在于官方NumericUpDown控件中的错误。
Nyerguds

149

而且,因为一站式地做事情总是更有趣...

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

注意:这不会阻止用户将其复制/粘贴到此文本框中。这不是清除数据的故障安全方法。


这不是通用解决方案,因为它仅适用于整数。我最近不得不实现这样的事情,最终我尝试将结果字符串解析为数字,并且仅在解析成功
后才

1
当多个方法处理KeyPress来自同一文本框的事件时,这可能不起作用。一个事件可能设置e.Handled为true,然后另一个事件可以将其设置为false。一般来说,最好使用if (...) e.Handled = true;
Nathaniel Jones

2
您可以禁用ShortcutsEnabled属性以防止通过键盘或菜单粘贴复制
Ahmad

3
哈哈!是! 一班轮!
Jamie L.

3
嗯 一个TextChanged是去在它与正则表达式可以解决事件复制粘贴;)
Nyerguds

51

我从上下文和您使用的标记中假设您正在编写.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);
    }
}

22
如果您键入数字的中间部分,这是否会产生非常奇怪的效果?
科林·皮卡德

5
而且也应该是:textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 1);
Pieniadz

3
如果第一个字符本身不是数字怎么办...在这种情况下不会减去1会引发错误....
manu_dilip_shah 2012年

6
另外,使用TextChanged代替KeyPress会创建一些递归,因为代码将在Remove方法之后跳入第二个TextChanged事件。
WEFX

2
您已为IsMatch函数切换了输入和模式参数。输入应该是第一个,然后是模式。msdn.microsoft.com/zh-CN/library/sdx2bds0(v=vs.110).aspx
Mibou,2014年

36

这是一个简单的独立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<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; }
}

对于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);

但是很好的是它可以与任何字符串和任何验证例程一起使用。


这很棒,很好,简单,易于使用,并且可以处理异常的输入尝试。谢谢!
WiredEarp

1
注意在2017年的版本,当有一个值,例如,1和你打回退,而如果你有说120和命中退格键三次,我们只剩下1它忽略
卡伦·佩恩

1
您的ValidatingTextbox到目前为止已经是我看过最好的实现了。简单有效。谢谢!
塞缪尔

19

这正是Validated / Validating事件设计的目的。

这是有关该主题的MSDN文章:http : //msdn.microsoft.com/zh-cn/library/system.windows.forms.control.validating.aspx

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

当您设置e.Cancel = True时,用户无法离开该字段,但是您需要向他们提供某种错误的反馈。我将框的背景颜色更改为浅红色,以指示问题。确保将其设置回SystemColors.Window调用具有良好值的Validating的时间。


1
+1是提及一种非常惯用的API方法。我对Windows窗体比较陌生,它是功能和MSDN文档的丛林,所以也要感谢指向的特定文档指针Validating<nitpick>OP提到立即禁止/指示无效字符是理想的选择,但Validating似乎要求在焦点生效之前将焦点移到另一种形式/控件上。</nitpick>不过,这是一个很好的方法,在更一般的情况下始终值得考虑。
威廉

13

试试MaskedTextBox。它采用简单的掩码格式,因此您可以将输入限制为数字或日期等。


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

12

您可以使用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();
    }
}

如果您使用过Undo(),它看起来应该可以很好地工作,但结果是StackOverflowException
德鲁·查平

看起来TextChanged属性是您想要撤消()例程的一部分。我在整个窗口中都有变量,并且正在使用public int txtBoxValue,如果tryParse无法正常运行,我将由txtBox.Text = txtBoxValue.ToString();
L. Zeda

8

这可能很有用。它允许“实”数值,包括正确的小数点和前面的正负号。从相关的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;
    }

6

我一直在研究一组组件以完成WinForms中缺少的内容,这是: Advanced Forms

特别是这是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);
    }
}

只需添加类似的内容即可myNumbericTextBox.RegexString = "^(\\d+|)$";


5

只需使用一个NumericUpDown控件,然后将这些难看的向下按钮的可见性设置为即可false

numericUpDown1.Controls[0].Visible = false;

NumericUpDown 实际上是一个控件集合,其中包含一个“旋转框”(向上按钮),一个文本框以及一些代码,以进行验证并将其全部链接在一起。

标记:

YourNumericUpDown.Controls[0].visible = false 

将隐藏按钮,同时保持底层代码处于活动状态。

虽然不是一个显而易见的解决方案,但它简单有效。.Controls[1]如果您想这样做,则会隐藏文本框部分。


接受的答案未包含有关如何删除上/下按钮的任何信息,如何这样做并不明显,因为没有人可读的界面来启用或禁用它们。NumericUpDown实际上是控件的集合,其中包含文本框和“旋转框”(向上按钮)以及一些处理输入验证的代码。
user2163234 '17

4

我在CodePlex上为此做了一些事情。

它通过拦截TextChanged事件来工作。如果结果是一个好的数字,它将被存储。如果出现问题,将恢复最后的有效价值。源代码太大了,无法在此处发布,但是这里是指向处理此逻辑核心的类的链接


4

只需在文本框中使用以下代码:

private void textBox1_TextChanged(object sender, EventArgs e)
{

    double parsedValue;

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

4

在带有文本框定义的网页中,我们可以添加一个onkeypress仅接受数字的事件。它不会显示任何消息,但可以防止您输入错误。它对我有用,用户只能输入数字。

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


2

我会在KeyDown事件中处理它。

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

2
诸如“ Backspace”,“ Delete”,“ Arrow-Key-Left”,“ Arrow-Key-Right”,“ Copy and Paste”,Numpad输入的数字(它们被交易为!digit)之类的键
user799821 2013年

只需添加其他一些这样的测试:if(!char.IsDigit(c)&& c!=(char)Keys.Back)
dnennis 2015年

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

试试这个很简单


2

看看WinForm中的输入处理

我已经在文本框中发布了使用ProcessCmdKey和OnKeyPress事件的解决方案。注释显示了如何使用正则表达式来验证按键并适当地阻止/允许。


2

嗨,您可以在文本框的textchanged事件中执行类似的操作。

这是一个演示

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

谢谢,它非常有用。
Kiran RS

2

似乎该问题的许多当前答案正在手动解析输入文本。如果您要查找特定的内置数​​字类型(例如intdouble),为什么不将工作委托给该类型的TryParse方法呢?例如:

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

如果您需要更通用但仍与Visual Studio设计器兼容的产品:

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

最后,如果您想要完全通用的东西,而不关心Designer支持:

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

整数和浮点数都必须接受,包括负数。

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

这是我的方法:

  1. 使用linq(易于修改过滤器)
  2. 复制/粘贴证明代码
  3. 按下禁止字符时保持插入符号位置
  4. 接受左零
  5. 以及任何尺寸的数字

    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

使用Fabio Iotti的答案中描述的方法,我创建了一个更通用的解决方案:

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”,其中包含所有非平凡的验证行为。剩下要做的就是从此类继承并使用所需的任何验证逻辑覆盖“ IsValid”方法。例如,使用此类,可以创建“ RegexedTextBox”,它仅接受与特定正则表达式匹配的字符串:

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

之后,从“ RegexedTextBox”类继承,我们可以轻松创建“ PositiveNumberTextBox”和“ PositiveFloatingPointNumberTextBox”控件:

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

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

1

抱歉唤醒死者,但我认为有人可能会觉得有用,以供将来参考。

这是我的处理方式。它处理浮点数,但可以很容易地将其修改为整数。

基本上你只能按0 - 9

之前只能有一个0

所有其他字符将被忽略,并保持光标位置。

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

这是一个快速修改的int版本:

    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
该解决方案是在警告时重新发明轮子。例如本地化。
朱利安·古托

1

这个可以复制,粘贴,拖放,按下来防止溢出,非常简单

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

别忘了用户可以在中粘贴无效文本TextBox

如果您想限制它,请遵循以下代码:

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

我也在寻找最好的方法来仅检查文本框中的数字和按键问题,因为它不支持通过右键单击或剪贴板复制粘贴,因此想出了此代码来验证光标何时离开文本字段并检查空字段。(适应版本的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似乎是一个错误的选择。
LarsTech

@LarsTech我认为已进行文本更改的内容即使在用户意识到错误并尝试修复它之前也可能导致错误消息框,因此我认为我会做得更好。您认为这种情况下最好的事件是什么?
2015年

@AlstonAntony最新评论,我知道。但是,只要在clickclick上激活一个简单的click事件就足够了吗?
塔卡里

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解决方案

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

资源 http://msdn.microsoft.com/zh-cn/library/system.windows.forms.control.keypress(v=VS.90).aspx

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


0

在按钮单击中,您可以通过for循环检查文本框的文本:

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

比较简单的答案:

_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());
};
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.