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
Comments
Anonymous
May 23, 2006
Thank you Irena - this is great!Anonymous
May 24, 2006
The comment has been removedAnonymous
May 27, 2006
PingBack from http://adamcaudill.com/2006/05/27/maskedtextbox-madness/Anonymous
June 21, 2006
At a customer's site, an application needed to format and accept formatted input for currencies. They...Anonymous
June 21, 2006
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.aspxAnonymous
January 18, 2007
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 NickOAnonymous
January 19, 2007
Use zeros instead of # in your mask; e.g. Mask = "0000.00" and you should get the expected resultAnonymous
February 27, 2007
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.Anonymous
January 16, 2008
Do you have a VB.NET implementation?Anonymous
July 10, 2008
I've found a simplier way: private void maskedTextBox1_KeyPress(object sender, KeyPressEventArgs e) { string buff = ""; int i; if (maskedTextBox1.MaskCompleted) { e.Handled = true; return; } char[] chars = maskedTextBox1.Text.PadLeft(5, ' ').ToCharArray(); for (i = 0; i < chars.Length-1; i++) chars[i] = chars[i+1]; chars[i] = e.KeyChar; for (i = 0; i < chars.Length; i++) buff += chars[i]; maskedTextBox1.Text = buff; }Anonymous
July 24, 2008
I am using a masked textbox to ip date in following format dd-MMM-yyyy. I've set the mask property as 00-AAA-0000 However if i assign text property of Masked textbox to a value like 11Jul2008 i can not delete first two characters from the masked textbox unless i delete remaining six characters first. Any idea what could be the reason.Anonymous
August 04, 2008
Hi I made a Inherited control about it. But It don´t work like see in this post. I put the control on a win forms , and then put the mask 0000.00. When i imput the digit in the control , it don´t shift the digit to right. Any boy can tell me how use this control on a win form.Anonymous
February 08, 2009
PingBack from http://www.sascha-hennig.de/csharp/maskedtextbox-and-custom-types