C# 上的价格/现金/货币文本框

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19215989/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 14:25:21  来源:igfitidea点击:

Textbox for price/cash/currency on C#

c#stringformatting

提问by athosbr99

I have a problem that is haunting me for a while. I tried some solutions but they didn't worked.

我有一个问题困扰了我一段时间。我尝试了一些解决方案,但没有奏效。

I have a textbox that is for cash input ($999,99 for example). However I need to automatically input the "," and "." to display the value correctly.

我有一个用于现金输入的文本框(例如 999,99 美元)。但是我需要自动输入“,”和“。” 以正确显示值。

I tried two solutions. One of them is this:

我尝试了两种解决方案。其中之一是这样的:

   private void tx_ValorUnidade_TextChanged(object sender, EventArgs e)
    {
        string value = tx_ValorUnidade.Text.Replace(",", "").Replace("R$", "");
        decimal ul;
        //Check we are indeed handling a number
        if (decimal.TryParse(value, out ul))
        {
            //Unsub the event so we don't enter a loop
            tx_ValorUnidade.TextChanged -= tx_ValorUnidade_TextChanged;
            //Format the text as currency
            tx_ValorUnidade.Text = string.Format(System.Globalization.CultureInfo.CreateSpecificCulture("pt-BR"), "{0:C2}", ul);
            tx_ValorUnidade.TextChanged += tx_ValorUnidade_TextChanged;
        }
    }

The result, however, is very weird.

然而,结果非常奇怪。

The other one is this:

另一种是这样的:

    private void tx_ValorUnidade_KeyUp(object sender, KeyEventArgs e)
    {
          if (!string.IsNullOrEmpty(tx_ValorUnidade.Text))
          {
              System.Globalization.CultureInfo culture = new System.Globalization.CultureInfo("en-US");
              int valueBefore = Int32.Parse(tx_ValorUnidade.Text, System.Globalization.NumberStyles.AllowThousands);
              tx_ValorUnidade.Text = String.Format(culture, "{0:N0}", valueBefore);
              tx_ValorUnidade.Select(tx_ValorUnidade.Text.Length, 0); *
          }
    }

This one kinda works, but there is a issue: if the user wants to insert somethink like $10,00 it can't. It also crashes after 5 numbers.

这有点工作,但有一个问题:如果用户想插入一些像 $10,00 这样的东西,它不能。它也会在 5 个数字后崩溃。

For original reference, I got the 2 codes from otherquestionshere.

作为原始参考,我从这里的其他问题中获得了 2 个代码。

How can I fix it? Am I using the examples wrong? Any thought is welcome.

我该如何解决?我使用的例子错了吗?欢迎任何想法。

采纳答案by Szymon

I think you will be better off when formatting when the user moves to the next control, e.g. like below. Otherwise it will be very confusing as the text will change itself as the user is typing:

我认为当用户移动到下一个控件时进行格式化会更好,例如如下所示。否则它会非常混乱,因为文本会随着用户输入而改变:

    private void textBox1_Leave(object sender, EventArgs e)
    {
        Double value;
        if (Double.TryParse(textBox1.Text, out value))
            textBox1.Text = String.Format(System.Globalization.CultureInfo.CurrentCulture, "{0:C2}", value);
        else
            textBox1.Text = String.Empty;
    }

回答by GreatNate

Some people might want to actually format a textbox as they type. So this is my solution if anyone is looking for one.

有些人可能希望在键入时实际格式化文本框。所以这是我的解决方案,如果有人正在寻找一个。

It actually assumes you are entering one digit at a time so therefore as you press "1" it assumes "$0.01" and when they press "2" it then assumes "$0.12" and so on and so forth.

它实际上假设您一次输入一位数字,因此当您按“ 1”时,它会假设“ $0.01”,当他们按“ 2”时,它会假设“ $0.12”,依此类推。

I could not find anything online about formatting as they typed. It has been tested and if any errors let me know.

我在网上找不到任何关于他们输入格式的信息。它已经过测试,如果有任何错误,请告诉我。

private void textBox1_TextChanged(object sender, EventArgs e)
{
    //Remove previous formatting, or the decimal check will fail including leading zeros
    string value = textBox1.Text.Replace(",", "")
        .Replace("$", "").Replace(".", "").TrimStart('0');
    decimal ul;
    //Check we are indeed handling a number
    if (decimal.TryParse(value, out ul))
    {
        ul /= 100;
        //Unsub the event so we don't enter a loop
        textBox1.TextChanged -= textBox1_TextChanged;
        //Format the text as currency
        textBox1.Text = string.Format(CultureInfo.CreateSpecificCulture("en-US"), "{0:C2}", ul);
        textBox1.TextChanged += textBox1_TextChanged;
        textBox1.Select(textBox1.Text.Length, 0);
    }
    bool goodToGo = TextisValid(textBox1.Text);
    enterButton.Enabled = goodToGo;
    if (!goodToGo)
    {
        textBox1.Text = "
    private void Form1_Load(object sender, EventArgs e)
    {
        textBox1.Text = "
private bool KeyEnteredIsValid(string key)
{
  Regex regex;
  regex = new Regex("[^0-9]+$"); //regex that matches disallowed text
  return regex.IsMatch(key);
}
.00"; textBox1.SelectionStart = inputBox.Text.Length; }
.00"; textBox1.Select(textBox1.Text.Length, 0); } } private bool TextisValid(string text) { Regex money = new Regex(@"^$(\d{1,3}(\,\d{3})*|(\d+))(\.\d{2})?$"); return money.IsMatch(text); }

To make it look nice I'd recommend starting the text box with the text $0.00 on the form load like so:

为了使它看起来不错,我建议在表单加载时使用文本 $0.00 开始文本框,如下所示:

private void TextBox1_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
  e.Handled = KeyEnteredIsValid(e.Text);
}

回答by Max Mazur

Just a slight modification to GreatNates answer.

只是对 GreatNates 的答案稍作修改。

txtCost.Text = String.Format("{0:c2}", myObj.Cost);

and insert this method into the textboxs preview input event like this.

并像这样将此方法插入到文本框预览输入事件中。

 Decimal val;
if (Decimal.TryParse(TxtCosPrice.Text, out val))
    TxtCosPrice.Text = val.ToString("C");
else
    MessageBox.Show("Oops!  Bad input!");

That way you make sure that you can't make any mistakes when typing anything. You are limited to numbers only with my methods, while nates methods are formatting your string.

这样您就可以确保在输入任何内容时不会犯任何错误。您只能使用我的方法使用数字,而 nates 方法正在格式化您的字符串。

Cheers.

干杯。

回答by Ashish-BeJovial

We can try following one as well.

我们也可以尝试跟随一个。

    private void textBox1_KeyUp(object sender, KeyEventArgs e)
        {
        e.SuppressKeyPress = TextBox2Currency((TextBox)sender, e.KeyValue);
        }

    private bool TextBox2Currency(TextBox sender,int keyval)
        {
        if ((keyval >= 48 && keyval <= 58) || keyval == 46 || keyval == 8)
            {
            int pos = sender.SelectionStart;
            int oriLen = sender.Text.Length;
            string currTx = sender.Text.Replace(".", "").ToCurrency();
            int modLen = currTx.Length;
            if (modLen != oriLen)
                pos += (modLen - oriLen);
            sender.Text = currTx;
            if ( pos>=0)
                sender.SelectionStart = pos;
            return false;
            }
        return true;
        }

回答by blind Skwirl

I struggled with this for hours too. I tried to use maskedTextBox but that was just clunky for the users to enter text. I also didn't like having to deal with the masking for calculations. I also looked into using the databinding formatting but that just seemed overkill.

我也为此挣扎了几个小时。我尝试使用 maskedTextBox 但这对于用户输入文本来说只是笨拙的。我也不喜欢为计算处理掩码。我还研究了使用数据绑定格式,但这似乎有点矫枉过正。

The way I ended up going was not to use a TextBox for inputting numbers. Use the NumericUpDown object instead. No need conversion and you can set your decimals and thousands commas in the properties if you like ;) I set my increment to 1000 since i was dealing with income.

我最终采用的方法是不使用 TextBox 来输入数字。请改用 NumericUpDown 对象。不需要转换,如果你愿意,你可以在属性中设置你的小数和千位逗号;) 因为我处理收入,所以我将我的增量设置为 1000。

Do be aware that the .Text that comes through will have commas when there is a penny decimal and amount over 1000 (i.e. 1,000.01) , otherwise the decimal and trailing 0s are dropped.

请注意,当有一个便士小数且金额超过 1000(即 1,000.01)时,通过的 .Text 将包含逗号,否则小数和尾随 0 将被删除。

I also found this short and sweet solution which worked well but was unneccesary with numericUpDown. You can put this on leave event.

我还发现了这个简短而甜蜜的解决方案,它运行良好,但与 numericUpDown 无关。你可以把它放在休假事件上。

##代码##

回答by Paolo Softlogica

This is my solution, it puts only dots, not money symbol. Hope can help somenone.

这是我的解决方案,它只放点,而不是货币符号。希望可以帮助某人。

##代码##