You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

文本框验证需求:仅允许数字后带小数点或逗号,附按键事件代码

Hey,我看你已经在做文本框的数字输入验证了,基础代码已经考虑到了区域文化的数字分隔符(小数点和千分位逗号),但还需要补充一些关键逻辑,才能满足「仅允许在数字后输入小数点/逗号、符号不能单独存在」的要求。我来帮你完善这个实现:

文本框数字输入验证(适配区域文化分隔符)

核心问题补充

你的现有代码只判断了允许输入的字符类型,但没处理以下关键规则:

  • 分隔符(小数点/千分位符)不能单独输入,必须跟在数字后面
  • 小数点只能出现一次
  • 千分位分隔符不能出现在小数点之后

完整按键事件代码实现

private void YourTextBox_KeyPress(object sender, KeyPressEventArgs e)
{
    TextBox targetTextBox = sender as TextBox;
    if (targetTextBox == null) return;

    CultureInfo currentCulture = System.Threading.Thread.CurrentThread.CurrentCulture;
    string decimalSeparator = currentCulture.NumberFormat.NumberDecimalSeparator;
    string groupSeparator = currentCulture.NumberFormat.NumberGroupSeparator;

    // 允许数字和退格键(Backspace),这是基础输入需求
    if (char.IsDigit(e.KeyChar) || e.KeyChar == '\b')
    {
        e.Handled = false;
        return;
    }

    // 处理小数点分隔符
    if (e.KeyChar.ToString() == decimalSeparator)
    {
        // 验证条件:
        // 1. 文本框已有内容(不能单独输入小数点)
        // 2. 文本框中还没有小数点(避免多个小数点)
        // 3. 光标前不是千分位分隔符(防止出现 "1,." 这种无效格式)
        bool isValidDecimalInput = !string.IsNullOrEmpty(targetTextBox.Text) 
                                  && !targetTextBox.Text.Contains(decimalSeparator)
                                  && (targetTextBox.SelectionStart == 0 || targetTextBox.Text[targetTextBox.SelectionStart - 1] != groupSeparator[0]);
        
        e.Handled = !isValidDecimalInput;
        return;
    }

    // 处理千分位分隔符
    if (e.KeyChar.ToString() == groupSeparator)
    {
        // 验证条件:
        // 1. 文本框已有内容(不能单独输入千分位符)
        // 2. 光标前是数字(不能在开头或非数字后输入)
        // 3. 光标位置不在小数点之后(千分位符只能在整数部分)
        bool isValidGroupInput = !string.IsNullOrEmpty(targetTextBox.Text)
                               && targetTextBox.SelectionStart > 0
                               && char.IsDigit(targetTextBox.Text[targetTextBox.SelectionStart - 1])
                               && !targetTextBox.Text.Substring(0, targetTextBox.SelectionStart).Contains(decimalSeparator);
        
        e.Handled = !isValidGroupInput;
        return;
    }

    // 所有不符合规则的字符一律拦截
    e.Handled = true;
}

额外补充:处理粘贴场景

只靠按键事件还不够,用户可能通过粘贴输入不符合规则的内容,建议再加个TextChanged事件来做二次验证:

private void YourTextBox_TextChanged(object sender, EventArgs e)
{
    TextBox targetTextBox = sender as TextBox;
    if (targetTextBox == null) return;

    CultureInfo currentCulture = System.Threading.Thread.CurrentThread.CurrentCulture;
    string decimalSeparator = currentCulture.NumberFormat.NumberDecimalSeparator;
    string groupSeparator = currentCulture.NumberFormat.NumberGroupSeparator;

    // 第一步:过滤掉所有非数字、非合法分隔符的字符
    string cleanedText = new string(targetTextBox.Text
        .Where(c => char.IsDigit(c) || c.ToString() == decimalSeparator || c.ToString() == groupSeparator)
        .ToArray());

    // 第二步:确保小数点只出现一次,且移除小数点后的千分位符
    int decimalPos = cleanedText.IndexOf(decimalSeparator);
    if (decimalPos != -1)
    {
        // 保留第一个小数点,移除后续的所有小数点
        cleanedText = cleanedText.Substring(0, decimalPos + 1) 
                    + cleanedText.Substring(decimalPos + 1).Replace(decimalSeparator, "");
        // 移除小数点后的千分位符(千分位只适用于整数部分)
        cleanedText = cleanedText.Substring(0, decimalPos + 1) 
                    + cleanedText.Substring(decimalPos + 1).Replace(groupSeparator, "");
    }

    // 第三步:如果清理后只剩分隔符,直接清空
    if (cleanedText == decimalSeparator || cleanedText == groupSeparator)
    {
        cleanedText = "";
    }

    // 避免无限触发TextChanged事件
    if (targetTextBox.Text != cleanedText)
    {
        targetTextBox.Text = cleanedText;
        targetTextBox.SelectionStart = targetTextBox.Text.Length;
    }
}

这样不管是手动输入还是粘贴内容,都能严格符合你要求的验证规则啦!

内容的提问来源于stack exchange,提问作者Ronald López

火山引擎 最新活动