I have a textbox in c# winforms.

   private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
    {
        if (!char.IsNumber(e.KeyChar) & (Keys)e.KeyChar != Keys.Back
                & e.KeyChar != ',')
        {
            e.Handled = true;
        }

        base.OnKeyPress(e);
    }

above code works very well however i can add 2 comma like "100,,00".How can i only let user add "100,00" or "100,000,000" with 1 comma as money format ?

Any help will be appreciated.

Thanks.

有帮助吗?

解决方案 2

As Crono stated in another answer, a MaskedTextBox is the best solution. But if you really want to add the constraints and formatting to your text box you could just parse the text into a decimal, then override the comma key altogether and only allow one decimal.

This is a bit hacked together but should achieve what you are looking for:

First create the event handler to not allow comma entry and only allow one decimal point

    private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
    {
        //Just don't let them type commas - We will format after the TextBox is left
        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;
        }
    }

Then create a little helper method to parse the value of your TextBox to a decimal

    private decimal GetValueFromTextBox(string input)
    {
        input = System.Text.RegularExpressions.Regex.Replace(input, @"[,$%]", String.Empty);
        //Could use Try parse here for better handling
        decimal output = Convert.ToDecimal(input);
        return output;
    }

Then just call the function from your TextBox_Leave event:

    private void textBox1_Leave(object sender, EventArgs e)
    {
        var value = GetValueFromTextBox(textBox1.Text);

        textBox1.Text = value.ToString("c");
    }

This will format the value in Currency format with the proper comma placement enforcing only one decimal point as well. Again NOT THE BEST SOLUTION (use a MaskedTextBox) but it will work for a normal TextBox control.

其他提示

Not a direct answer to your actual question but most definitely an advice you should consider: use a MaskedTextBox for this, not a TextBox.

A MaskedTextBox has a Mask property that acts as a pattern for text values. In your case, the appropriate mask would likely be #,###.##. Note that depending on the culture your assembly is on the decimal separator may be something else than a comma. Still, you'll be able to convert this to a numeric value, which is most certainly what you want anyway.

UPDATE:

As an additional advice, some 3rd party vendors like do offer controls with more advanced mask inputs that can use traditional masks as well as regex-based validators. If you can afford the money it might be something to look into.

You can use the NumericUpDown control to avoid any manual verification of numbers.

You can limit the permitted input in a textbox by usin a MaskedTextbox,

If you prefer to test this logically/manually, add something like: !textBox1.Text.Contains(',').

That will return true only if there is not already a comma in the textbox.

Edit: Actually, I'm not sure if the newly added comma will be included before or after the keypress-event - if it is included, then you might have to use count instead:

if( ... && (textBox1.Text.Count(c => c == ',') <= 1) ) 
{
    ....
}

PS: I would refactor this code and move the tests out into separate methods for cleanliness, so the main test would look something like this:

if(IsValidChar(e.KeyChar) && IsOnlyOneCommaProvided()){ 
    ...
}

you could use regex like [\d]*,[\d]* that would ensure it only matches the constraint of having a maximum of one comma between numbers.

Update: something along the lines of this:

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    var newString = textBox1.Text += e.KeyChar;
    if(!Regex.IsMatch(newString, "[\d]*,[\d]*"))
        e.Handled = true;

    base.OnKeyPress(e);
}

I recommend checking into 3rd party controls. They save a lot of time (which is money) and headaches. The DevExpress TextEdit control does this… it’s a simple option that takes no time at all to set. I'm assuming all the others (Telerik, Infragistics, etc) do it too.

How about javascript solution?

It benefits from being platform independent, and takes care of cursor position within text field, plus no processing on server side which is always nice.

One downside is if JS is disabled, another you have to 'clean' values of commas on server side when they get submitted. All and all I would consider it to be far more elegant solution.

just add to your textbox type='tel' attribute like:

<input type='tel' />



<script type="text/javascript">
    $(function () {
        $("[type='tel']").keydown(function (event) {
            var position = this.selectionStart;
            var $this = $(this);
            var val = $this.val();
            if (position == this.selectionEnd &&
                ((event.keyCode == 8 && val.charAt(position - 1) == "," && val.substr(0, position - 1).indexOf(".") == -1)
                || (event.keyCode == 46 && val.charAt(position) == "," && val.substr(0, position).indexOf(".") == -1))) {
                event.preventDefault();
                if (event.keyCode == 8) {
                    $this.val(val.substr(0, position - 2) + val.substr(position));
                    position = position - 2;
                } else {
                    $this.val(val.substr(0, position) + val.substr(position + 2));
                }
                $this.trigger('keyup', { position: position });
            } else {
                this.dispatchEvent(event);
            }
        });

                $("[type='tel']").keyup(function(event, args) {
                        if (event.which >= 37 && event.which <= 40) {
                                event.preventDefault();
                        }

                        var position = args ? args.position : this.selectionStart;
                        var $this = $(this);
                        var val = $this.val();
                        var parts =val.split(".");
                    var valOverDecimalPart = parts[0];
                        var commaCountBefore = valOverDecimalPart.match(/,/g) ? valOverDecimalPart.match(/,/g).length : 0;
                        var num = valOverDecimalPart.replace(/[^0-9]/g, '');
                        var result = parts.length == 1 ? num.replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,") : num.replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,") +"."+ parts[1].replace(/[^0-9.]/g,"");
                    $this.val(result);
                    var commaCountAfter = $this.val().match(/,/g) ? $this.val().match(/,/g).length : 0;
                        position = position + (commaCountAfter - commaCountBefore);
                        this.setSelectionRange(position, position);
                });
            });
    </script>
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top