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