Welcome to MSDN Blogs Sign in | Join | Help

SYSK 87: A Better MaskedTextBox For Currency Fields

You may want to save this one off and put it in your personal toolbox…

 

The MaskedTextBox that comes with .NET has a few limitations – it does not automatically shift your digits.  For example, if I enter a mask of 0000.00, and enter number 12, I’d expect to see __12.00; instead, I see 12__.__.

 

Below is a custom control that “fixes” that behavior.  NOTE: for the control to work right, use zeros in the mask, not nines or pound sign.

 

public class CurrencyTextBox : System.Windows.Forms.MaskedTextBox

{

    public CurrencyTextBox()

    {

        base.TextMaskFormat = System.Windows.Forms.MaskFormat.IncludePromptAndLiterals;

    }

 

    public bool TryGetValue(out decimal data)

    {

        return decimal.TryParse(RemovePromptAndLiterals(this.Text), out data);           

    }

 

    public decimal Value

    {

        get

        {

            decimal result = 0;

            TryGetValue(out result);

 

            return result;

        }

        set

        {

            base.Text = ReplaceLeadingZeros(value.ToString(this.Mask));

        }

    }

 

    private string RemovePromptAndLiterals(string data)

    {

        return data != null ? data.Replace(" ", "").Replace(this.PromptChar.ToString(), "").Replace("$", "") : "";

    }

 

    protected override void OnValidated(EventArgs e)

    {

        decimal data = 0;

        if (TryGetValue(out data) == true)

        {

            base.Text = ReplaceLeadingZeros(data.ToString(this.Mask));

        }

       

        base.OnValidated(e);

    }

 

    protected override void OnTextChanged(EventArgs e)

    {

        base.OnTextChanged(e);

    }

 

    public override string Text

    {

        get

        {

            return base.Text;

        }

        set

        {

            decimal data = 0;

            if (decimal.TryParse(RemovePromptAndLiterals(value), out data) == true)

            {

                base.Text = ReplaceLeadingZeros(data.ToString(this.Mask));

            }

            else

            {

                base.Text = value;

            }

        }

    }

 

    protected override void OnKeyPress(System.Windows.Forms.KeyPressEventArgs e)

    {

        if (e.KeyChar == '.')

        {

            decimal data = 0;

            if (TryGetValue(out data) == true)

            {

                string mask = this.Mask.Replace(".00", ".##").Replace(".99", ".##");

                base.Text = ReplaceLeadingZeros(data.ToString(mask));

            }

        }

 

        base.OnKeyPress(e);

    }

 

    protected string ReplaceLeadingZeros(string data)

    {

        char[] chars = data.ToCharArray();

 

        for (int i = 0; i < chars.Length; i++)

        {

            if (chars[i] != '$' && chars[i] != ' ')

            {

                if (chars[i] == '0')

                    chars[i] = this.PromptChar;

                else

                    break;

            }

        }

 

        return new string(chars);

    }

}

[6/21/2006]  Check out Sven Aelterman's post where he improved on the code above by adding culture awareness and thousand separator awareness:  http://www.adduxis.com/blogs/blogs/sven/archive/2006/06/21/18.aspx 

 

Published Tuesday, March 21, 2006 5:26 AM by irenak
Filed under:

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# re: SYSK 87: A Better MaskedTextBox For Currency Fields

Tuesday, May 23, 2006 7:52 PM by Ray Muirhead
Thank you Irena - this is great!

# re: SYSK 87: A Better MaskedTextBox For Currency Fields

Wednesday, May 24, 2006 3:47 PM by Joel@YA
Thanks for this.  As a suggestion, some comments in the code would be helpful.  If I wanted to expand this to include support of '##' hash marks, what would that look like?

# Adam Caudill&#8217;s Blog &raquo; MaskedTextBox Madness

Saturday, May 27, 2006 11:45 AM by Adam Caudill’s Blog » MaskedTextBox Madness

# A Currency MaskedTextBox for .NET 2.0

Wednesday, June 21, 2006 6:17 PM by Sven's Blog
At a customer's site, an application needed to format and accept formatted input for currencies. They...

# Culture and Thousand Separator Awareness

Wednesday, June 21, 2006 6:18 PM by Sven Aelterman
I've added comments to Irena's code, and then set out to add support for non-US English cultures and the thousand separator.

The result is available through http://www.adduxis.com/blogs/blogs/sven/archive/2006/06/21/18.aspx

# re: SYSK 87: A Better MaskedTextBox For Currency Fields

Friday, January 19, 2007 12:16 AM by NickO

Shifting of numbers to the left is the least of problems I'd worry about.

Try to set the Mask = "####.##", then set

maskedtextbox1.text = "15.25"

The resul yo'd get is 1525.  ". The mask completely ignores the decimal point.

You are right: you'd need to write a function that would take care of inefficiencies of Masked Textbox design

NickO

# SYSK 87: Reply to NickO

Friday, January 19, 2007 10:32 AM by irenak

Use zeros instead of # in your mask; e.g. Mask = "0000.00" and you should get the expected result

# re: SYSK 87: A Better MaskedTextBox For Currency Fields

Tuesday, February 27, 2007 4:45 PM by Rodel E. Dagumampan

hi irena, nice post but i have some comments. it is better if you will use the CultureInfo and CurrentCulture of the applications so you can use the correct decimal separators, parethesis, currency symbols and numbver digits. Replacing "$" sign is no good to me eso for multi-currency applications such as e-commerce, trading, sales automations and erp.

# re: SYSK 87: A Better MaskedTextBox For Currency Fields

Wednesday, January 16, 2008 9:23 AM by mike

Do you have a VB.NET implementation?

Leave a Comment

(required) 
required 
(required) 
 
Page view tracker