我有一个带有文本框控件的Windows窗体应用程序,我只想接受整数值.在过去,我通过重载KeyPress事件并删除不符合规范的字符来完成这种验证.我看过MaskedTextBox控件,但是我想要一个更通用的解决方案,可以使用正则表达式,或者依赖于其他控件的值.
理想情况下,这将表现为按下非数字字符将不产生结果或立即向用户提供关于无效字符的反馈.
两种选择:
请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
而且因为在一条线上做东西总是更有趣......
private void textBox1_KeyPress(object sender, KeyPressEventArgs e) { e.Handled = !char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar); }
注意:这不会阻止用户复制/粘贴到此文本框中.这不是一种清理数据的失败安全方法.
我假设您从上下文和您使用的标签编写.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);
}
}
这是一个简单的独立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 EventHandlerTextValidating; 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);
但它的好处是它适用于任何字符串和任何验证例程.
这正是验证/验证事件的设计目标.
以下是关于该主题的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时将其重新设置为.
试试MaskedTextBox.它采用简单的掩码格式,因此您可以将输入限制为数字或日期或其他任何内容.
您可以使用该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(); } }
这可能很有用.它允许"实际"数值,包括正确的小数点和前面的加号或减号.从相关的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; }
我一直在研究一组组件来完成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+|)$";
就足够了.