如何制作只接受数字的文本框?
我有一个窗体应用程序与一个文本框控件,我只想接受整数值。 在过去,我通过重载KeyPress事件来完成这种validation,只是删除不符合规范的字符。 我已经看了MaskedTextBox控件,但我想要一个更通用的解决scheme,可能与正则expression式一起工作,或者依赖于其他控件的值。
理想情况下,这将performance为按非数字字符不会产生任何结果,或者立即向用户提供关于无效字符的反馈。
两个选项:
-
改用
NumericUpDown
。 NumericUpDown为你做了过滤,这很好。 当然,它也使您的用户能够按下键盘上的向上和向下箭头来递增和递减当前值。 -
处理适当的键盘事件,以防止数字input。 这两个事件处理程序在一个标准的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; } }
您可以删除'.'
的检查'.'
(以及后续检查多个'.'
)如果您的文本框不应该允许小数位。 如果你的文本框应该允许负值,你也可以添加一个'-'
的检查。
如果要限制用户的数字位数,请使用: textBox1.MaxLength = 2; // this will allow the user to enter only 2 digits
textBox1.MaxLength = 2; // this will allow the user to enter only 2 digits
只是因为在一条线上做东西总是更有趣…
private void textBox1_KeyPress(object sender, KeyPressEventArgs e) { e.Handled = !char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar); }
注意:这不会阻止用户复制/粘贴到此文本框中。 这不是一个安全的方式来清理您的数据。
我假设从上下文和你使用的标签,你正在写一个.NET C#应用程序。 在这种情况下,您可以订阅文本更改事件,并validation每个关键笔划。
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); } }
这是一个简单的独立Winforms自定义控件,从标准TextBox派生,只允许System.Int32input(它可以很容易地适应其他types,如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年更新 :我的第一个答案有一些默认值:
- 您可以input比给定types的整数长的东西(例如2147483648大于Int32.MaxValue);
- 更一般地说,对input的结果没有真正的validation;
- 它只处理int32,你将不得不为每个types(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); } }
或W / O派生,使用新的TextValidating事件像这样:
var vtb = new ValidatingTextBox(); ... vtb.TextValidating += (sender, e) => e.Cancel = !int.TryParse(e.NewText, out int i);
但有什么好处呢,它适用于任何string和任何validation例程。
这正是validation/validation事件的devise目的。
以下是有关该主题的MSDN文章: http : //msdn.microsoft.com/zh-cn/library/system.windows.forms.control.validating.aspx
TL; DR版本:检查Validating事件中的.Text属性,并在数据无效时设置e.Cancel=True
。
当你设置e.Cancel = True时,用户不能离开这个字段,但是你需要给他们一些反馈,告诉他们有什么错误。 我把箱子的背景颜色改成浅红色表示有问题。 确保在调用具有良好值的“validation”时将其设置回SystemColors.Window
。
尝试一个MaskedTextBox 。 它需要一个简单的掩码格式,所以你可以限制input数字或date或任何。
您可以使用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(); } }
我一直在处理一些组件的集合,以完成WinForms中缺less的东西,这里是: 高级forms
特别是这是正则expression式文本框的类
/// <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+|)$";
应该足够了。
我在CodePlex上为此做了一些事情。
它通过拦截TextChanged事件工作。 如果结果是一个好数字,它将被存储。 如果出现错误,最后的好价值将会被恢复。 源代码有点太大,不能在这里发布,但是这里有一个指向处理这个逻辑核心的类的链接 。
这可能是有用的。 它允许“真正的”数值,包括正确的小数点和前面的加号或减号。 在相关的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; }
只需在文本框中使用此代码:
private void textBox1_TextChanged(object sender, EventArgs e) { double parsedValue; if (!double.TryParse(textBox1.Text, out parsedValue)) { textBox1.Text = ""; } }
在我们的文本框定义的网页中,我们可以添加一个onkeypress
事件来接受数字。 它不会显示任何消息,但会阻止您input错误。 它为我工作,除了数字用户不能input任何内容。
<asp:TextBox runat="server" ID="txtFrom" onkeypress="if(isNaN(String.fromCharCode(event.keyCode))) return false;">
你可以使用TextChanged / Keypress事件,使用正则expression式来过滤数字并采取一些行动。
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; } } }
试试这个很简单
看看在WinForminput处理
我已经发布我的解决scheme,在文本框上使用ProcessCmdKey和OnKeyPress事件。 评论显示您如何使用正则expression式来validation按键和阻止/允许适当。
嗨,你可以在文本框的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; }
这个问题的许多当前答案似乎是手动parsinginput文本。 如果你正在寻找一个特定的内置数值types(例如int
或者double
),为什么不把这个工作委派给那个types的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的devise器兼容:
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; } } }
不好意思把死人叫醒,但我想有人会觉得这对于将来的参考很有用。
这是我如何处理它。 它处理浮点数,但可以很容易地修改为整数。
基本上你只能按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; }
我会在KeyDown事件中处理它。
void TextBox_KeyDown(object sender, KeyEventArgs e) { char c = Convert.ToChar(e.PlatformKeyCode); if (!char.IsDigit(c)) { e.Handled = true; } }
这个工作与复制和粘贴,拖放,关键,防止溢出,很简单
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); } } }
我也在寻找最好的方法来检查只在文本框中的数字和按键问题是它不支持复制粘贴通过右键单击或剪贴板,所以想出了这个代码,validation当光标离开文本字段,也检查空的领域。 (改编的新版本)
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(); } }
int Number; bool isNumber; isNumber = int32.TryPase(textbox1.text, out Number); if (!isNumber) { (code if not an integer); } else { (code if an integer); }
3解决scheme
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的另一个解决scheme
// 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/en-us/library/system.windows.forms.control.keypress(v=VS.90).aspx
3)使用MaskedTextBox: http : //msdn.microsoft.com/en-us/library/system.windows.forms.maskedtextbox.aspx
在button单击您可以通过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 }
更简单的答案:
_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()); };
FAIL-SAFE和简单的“recursion”方法,可以与多个文本框一起使用。
它阻止错误的键盘input字符,也粘贴值等。它只接受整数, 最大数字长度是一个stringtypes的最大长度 (这是int,真的很长!)
public void Check_If_Int_On_TextChanged(object sender, EventArgs e) { // This method checks that each inputed character is a number. Any non-numeric // characters are removed from the text TextBox textbox = (TextBox)sender; // If the text is empty, return if (textbox.Text.Length == 0) { return; } // Check the new Text value if it's only numbers byte parsedValue; if (!byte.TryParse(textbox.Text[(textbox.Text.Length - 1)].ToString(), out parsedValue)) { // Remove the last character as it wasn't a number textbox.Text = textbox.Text.Remove((textbox.Text.Length - 1)); // Move the cursor to the end of text textbox.SelectionStart = textbox.Text.Length; } }
我喜欢简洁的代码
private void xmm_textbox_KeyPress(object sender, KeyPressEventArgs e) { double x; e.Handled = !double.TryParse(((TextBox)sender).Text, out x); }
不要忘记,用户可以将无效的文本粘贴到文本框中。 如果你想限制,请按照下面的代码:
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; }
Here is a simple solution that works for me. public static bool numResult; public static bool checkTextisNumber(string numberVal) { try { if (numberVal.Equals(".")) { numResult = true; } else if (numberVal.Equals("")) { numResult = true; } else { decimal number3 = 0; bool canConvert = decimal.TryParse(numberVal, out number3); if (canConvert == true) { numResult = true; } else numResult = false; } } catch (System.Exception ex) { numResult = false; } return numResult; } string correctNum; private void tBox_NumTester_TextChanged(object sender, TextChangedEventArgs e) { if(checkTextisNumber(tBox_NumTester.Text)) { correctNum = tBox_NumTester.Text; } else { tBox_NumTester.Text = correctNum; } }