【问题标题】:Validate currency textbox验证货币文本框
【发布时间】:2026-01-09 06:40:02
【问题描述】:

我正在使用 WinForm。我有一个文本框和一个按钮。

目标:按钮应验证文本框是否为货币格式。如果文本框是货币格式,则消息应显示货币格式。如果不是,则消息应显示错误格式错误。

货币格式示例:

1,234.00 美元

$12,345.00

$123,000.00

1.00 美元

更新:

这是我的,但这是错误的。

    Private void button3_Click(object sender, EventArgs e)
    {    
        currencyTextbox = Convert.ToString(textBox4.Text);

        string money = currencyTextbox;

        string s = currencyTextbox;
        float f;
        if (float.TryParse(s, NumberStyles.AllowCurrencySymbol 
            | NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands, 
            CultureInfo.GetCultureInfo("en-US"), out f))
        {
            MessageBox.Show("Ok");
        }
        else
        {
            MessageBox.Show("Wrong");
        }
     }

测试用例:

$12.00 - 好的

12,000 美元 - 好的

$12,3,00 - OK - (无效)

$12,3,00# - 错误

【问题讨论】:

    标签: c# .net winforms validation textbox


    【解决方案1】:

    数字(本例中为decimal)与其字符串表示(本例中为货币)不同。这就是为什么您必须首先从字符串的角度分析输入(格式是否满足?),然后从数字的角度分析。有一些方法可以一次性执行分析(如其他答案中所建议的那样),尽管它们不能提供您所追求的确定(即,它是否是一种货币;理解为仅仅是数字是错误的)。

    示例代码:

    private void btn_Click(object sender, EventArgs e)
    {
        //Note: ideally, curCulture shouldn't be defined here (but globally or  
        //passed as argument), but otherwise my code would be somehow incomplete.
        CultureInfo curCulture = new CultureInfo("en-US", true);
    
        bool isOK = false;
        string[] temp = totalTextBox.Text.Trim().Split(new string[] { curCulture.NumberFormat.CurrencySymbol }, StringSplitOptions.None);
        if (temp.Length == 2 && temp[0].Trim().Length == 0)
        {
            decimal outVal = 0m;
            if (decimal.TryParse(temp[1], out outVal)) isOK = true;
        }
    
        MessageBox.Show(isOK ? "currency format" : "error wrong format");
    
    }
    

    注意几点:

    • curCulture 应该是你想要的格式(你甚至可以 考虑不同的文化/货币/格式)。从你的例子看来,你 想要:CultureInfo curCulture = new CultureInfo("en-US", true);
    • 输入字符串的分析可以根据需要复杂。例如:在发布的代码中,我还确保货币符号位于第一个位置。

    ---- UPDATE(考虑千位分隔符的十进制解析问题)

    在确认提议的Decimal.TryParse(和其他等效方法)在涉及数千个分隔符(组分隔符)时不能提供预期的结果后,我决定编写下面的代码来处理此类问题. 在任何情况下,请记住,我在这些情况下没有太多经验(即处理错误的十进制输入占数千个分隔符),这就是为什么不确定是否有更有效的方法来解决这个问题(尽管建议的分析肯定很快)。

    private void btn_Click(object sender, EventArgs e)
    {
        //Note: ideally, curCulture shouldn't be defined here (but globally or  
        //passed as argument), but otherwise my code would be somehow incomplete.
        CultureInfo curCulture = new CultureInfo("en-US", true);
    
        bool isOK = false;
        string[] temp = totalTextBox.Text.Trim().Split(new string[] { curCulture.NumberFormat.CurrencySymbol }, StringSplitOptions.None);
        if (temp.Length == 2 && temp[0].Trim().Length == 0)
        {
            isOK = isDecimalOK(temp[1], curCulture);
        }
    
        MessageBox.Show(isOK ? "currency format" : "error wrong format");
    }
    
    private bool isDecimalOK(string inputString, CultureInfo curCulture)
    {
        bool isOK = false;
    
        string[] temp = inputString.Split(new string[] { curCulture.NumberFormat.CurrencyDecimalSeparator }, StringSplitOptions.None);
        if (temp.Length > 2) return isOK;
    
        int outVal0 = 0;
        if (!int.TryParse(temp[0], NumberStyles.AllowThousands, curCulture, out outVal0)) return isOK;
        else if (analyseThousands(temp[0], curCulture))
        {
            isOK = (temp.Length == 2 ? int.TryParse(temp[1], NumberStyles.Integer, curCulture, out outVal0) : true);
        }
    
        return isOK;
    }
    
    private bool analyseThousands(string intInput, CultureInfo curCulture)
    {
    
        string[] temp2 = intInput.Split(new string[] { curCulture.NumberFormat.CurrencyGroupSeparator }, StringSplitOptions.None);
    
        if (temp2.Length >= 2)
        {
            if (temp2[0].Trim().Length == 0) return false;
            else
            {
                for (int i2 = 1; i2 < temp2.Length; i2++)
                {
                    if (!curCulture.NumberFormat.CurrencyGroupSizes.Contains(temp2[i2].Length)) return false;
                }
            }
        }
    
        return true;
    }
    

    【讨论】:

    • 您好,感谢您的解释。这段代码在 { curCulture.我如何使它有效。
    • @LearningToCode 我在代码下方的 cmets 中解释它:根据需要定义它。我猜curCulture = new CultureInfo("en-US"); 就是你要找的。在 bool isOK = false; 上面写下这一行以防万一,将立即编辑我的答案。
    • 也许我写错了。我是这样写的:: { curCulture = new CultureInfo("en-US").NumberFormat.CurrencySymbol }, StringSplitOptions.None);
    • @LearningToCode 看看我更新的答案(另请阅读我写的评论)。
    • 由于解析非常具体,尝试使用CultureInfo(string, bool)构造函数。我是那种会更改这些设置并喜欢破坏人们的程序的人;)
    【解决方案2】:

    你可以尝试使用正则表达式:

    var moneyR = new Regex(@"^\$(((\d{1,3},)+\d{3})|\d+)(\.\d{2}){0,1}$");
    if (moneyR.IsMatch(yourValue))
    {
        MessageBox.Show("Ok");
    }
    else
    {
        MessageBox.Show("Wrong");
    }
    

    【讨论】:

      【解决方案3】:

      要检查格式,您可以尝试像这样在浮点数中解析它:

              string s = "$123.78";
              float f;
              if (float.TryParse(s, NumberStyles.Any, CultureInfo.GetCultureInfo("en-US"), out f))
              {
                  // OK
              }
              else
              {
                  // WRONG
              }
      

      【讨论】:

      • 我对此进行了测试。这给了我一个错误。此代码接受不正确的 $12,3,00。
      • 请看TryParse方法的第二个参数,我用的是“Any”,但它会允许这样的异常数字。放在那里 NumberStyles.AllowCurrencySymbol | NumberStyles.AllowDecimalPoint 而不是 Any 并查看结果
      • 代码似乎几乎可以工作。这些是测试用例 $11-正确 $11.00-正确 $11,000.00-错误 $11,000-错误 $11,00-错误
      • @LearningToCode 添加NumberStyles.AllowThousands 并查看NumberStyles Enumeration
      • @RubensFarias 我在其中添加了NumberStyles.AllowThousands。代码仍然不正确。测试用例:(123,0,1 - 正确)(123,0,1.00 - 正确)(123,0,1.00@ - 错误)(1234 - 正确)
      【解决方案4】:

      试试这个,应该可以的

      string money = "$12,345.00";
      float f;
      if (float.TryParse(money, NumberStyles.Currency, CultureInfo.GetCultureInfo("en-US"), out f))
      {
         // valid
      }
      else
      {
          // invalid 
      }
      

      调试信息:

      输出:

      【讨论】:

      • 我认为有人投了反对票,因为它与另一个答案相似。我测试了这段代码,它是无效的。此代码接受:22,2.3 @X-TECH
      • 我也在我的机器上检查过它,它工作 100% 正确
      • 它可能也被否决了,因为它是一个简单的代码 sn-p 转储,没有解释或其他任何内容。 OP 很可能会从您的回答中学到很少/什么都没有。