我有一个windows窗体应用程序与一个文本框控件,我想只接受整数值。在过去,我通过重载KeyPress事件并删除不符合规范的字符来进行这种验证。我已经看了MaskedTextBox控件,但我想一个更通用的解决方案,可以与也许正则表达式,或依赖于其他控件的值。
理想情况下,按下非数字字符要么不产生结果,要么立即向用户提供关于无效字符的反馈。
我有一个windows窗体应用程序与一个文本框控件,我想只接受整数值。在过去,我通过重载KeyPress事件并删除不符合规范的字符来进行这种验证。我已经看了MaskedTextBox控件,但我想一个更通用的解决方案,可以与也许正则表达式,或依赖于其他控件的值。
理想情况下,按下非数字字符要么不产生结果,要么立即向用户提供关于无效字符的反馈。
当前回答
我从上下文和您使用的标记假设您正在编写一个。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,你必须写特定的TextBox衍生控件为每种类型(Int64等)
所以我提出了另一个更通用的版本,它仍然支持复制/粘贴,+和-号等。
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派生,使用新的textvalididating事件,像这样:
var vtb = new ValidatingTextBox();
...
vtb.TextValidating += (sender, e) => e.Cancel = !int.TryParse(e.NewText, out int i);
但它的优点是它适用于任何字符串和任何验证例程。
这是我的方法:
using linq (easy to modify filter) copy/paste proof code keeps caret position when you press a forbidden character accepts left zeroes and any size numbers 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; } }
看一下WinForm中的输入处理
我已经发布了我的解决方案,在文本框上使用ProcessCmdKey和OnKeyPress事件。注释向您展示了如何使用Regex来验证键按和适当地阻止/允许。
我会在KeyDown事件中处理它。
void TextBox_KeyDown(object sender, KeyEventArgs e)
{
char c = Convert.ToChar(e.PlatformKeyCode);
if (!char.IsDigit(c))
{
e.Handled = true;
}
}
两个选择:
Use a NumericUpDown instead. NumericUpDown does the filtering for you, which is nice. Of course it also gives your users the ability to hit the up and down arrows on the keyboard to increment and decrement the current value. Handle the appropriate keyboard events to prevent anything but numeric input. I've had success with this two event handlers on a standard 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;//这将允许用户只输入2位数字