我有一个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*$") { }
}

其他回答

我在CodePlex上做了一些东西。

它通过拦截TextChanged事件来工作。如果结果是一个好的数字,它将被存储。如果是错误的,最后的好值将恢复。源代码有点太大,不适合在这里发布,但这里有一个指向处理此逻辑核心的类的链接。

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

两个选择:

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位数字

使用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*$") { }
}

最简单粗暴的方法是使用组合框而不是带有只读的文本框。当然,只有当你希望用户使用一个合理的整数集,而不是试图接近无穷大时,它才有用。