我有一个windows窗体应用程序与一个文本框控件,我想只接受整数值。在过去,我通过重载KeyPress事件并删除不符合规范的字符来进行这种验证。我已经看了MaskedTextBox控件,但我想一个更通用的解决方案,可以与也许正则表达式,或依赖于其他控件的值。
理想情况下,按下非数字字符要么不产生结果,要么立即向用户提供关于无效字符的反馈。
我有一个windows窗体应用程序与一个文本框控件,我想只接受整数值。在过去,我通过重载KeyPress事件并删除不符合规范的字符来进行这种验证。我已经看了MaskedTextBox控件,但我想一个更通用的解决方案,可以与也许正则表达式,或依赖于其他控件的值。
理想情况下,按下非数字字符要么不产生结果,要么立即向用户提供关于无效字符的反馈。
当前回答
使用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"类继承,我们可以很容易地创建" positivevenumbertextbox "和"PositiveFloatingPointNumberTextBox"控件:
public sealed class PositiveNumberTextBox : RegexedTextBox {
public PositiveNumberTextBox() : base(@"^\d*$") { }
}
public sealed class PositiveFloatingPointNumberTextBox : RegexedTextBox {
public PositiveFloatingPointNumberTextBox()
: base(@"^(\d+\" + CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator + @")?\d*$") { }
}
其他回答
很抱歉吵醒死人,但我想有人可能会觉得这对将来的参考有用。
以下是我的处理方法。它处理浮点数,但可以很容易地修改为整数。
基本上你只能按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;
}
int Number;
bool isNumber;
isNumber = int32.TryPase(textbox1.text, out Number);
if (!isNumber)
{
(code if not an integer);
}
else
{
(code if an integer);
}
不要忘记用户可以在文本框中粘贴无效文本。
如果你想限制它,遵循下面的代码:
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;
}
在按钮点击,你可以检查文本框的文本循环:
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
}
我已经为各种验证创建了一个可重用的文本框扩展类,并考虑共享它。
您所需要做的就是引发一个TextChange事件,然后调用Validate方法。它是这样的:
private void tbxAmount_TextChanged(object sender, EventArgs e)
{
tbxAmount.Validate(TextValidator.ValidationType.Amount);
}
下面是扩展类:
public static class TextValidator
{
public enum ValidationType
{
Amount,
Integer
}
/// <summary>
/// Validate a textbox on text change.
/// </summary>
/// <param name="tbx"></param>
/// <param name="validationType"></param>
public static void Validate(this TextBox tbx, ValidationType validationType)
{
PerformValidation(tbx, validationType);
tbx.Select(tbx.Text.Length, 0);
}
private static void PerformValidation(this TextBox tbx, ValidationType validationType)
{
char[] enteredString = tbx.Text.ToCharArray();
switch (validationType)
{
case ValidationType.Amount:
tbx.Text = AmountValidation(enteredString);
break;
case ValidationType.Integer:
tbx.Text = IntegerValidation(enteredString);
break;
default:
break;
}
tbx.SelectionStart = tbx.Text.Length;
}
private static string AmountValidation(char[] enteredString)
{
string actualString = string.Empty;
int count = 0;
foreach (char c in enteredString.AsEnumerable())
{
if (count >= 1 && c == '.')
{ actualString.Replace(c, ' '); actualString.Trim(); }
else
{
if (Char.IsDigit(c))
{
actualString = actualString + c;
}
if (c == '.')
{
actualString = actualString + c; count++;
}
else
{
actualString.Replace(c, ' ');
actualString.Trim();
}
}
}
return actualString;
}
private static string IntegerValidation(char[] enteredString)
{
string actualString = string.Empty;
foreach (char c in enteredString.AsEnumerable())
{
if (Char.IsDigit(c))
{
actualString = actualString + c;
}
else
{
actualString.Replace(c, ' ');
actualString.Trim();
}
}
return actualString;
}
}
你可以在这里找到完整的代码