I think I understand what you are asking for. You are looking to automatically format all text boxes on a form, including new text boxes which are dynamically added.
To achieve this, the first step is to set up a generic event handler when focus is lost to any currency text box:
void OnCurrencyTextBoxLeave(object sender, EventArgs e)
{
if (sender is TextBox)
{
decimal value;
var textBox = (TextBox)sender;
if (decimal.TryParse(textBox.Text, out value))
{
textBox.Text = value.ToString("C");
}
else textBox.Text = string.Empty;
}
}
Then we can add two functions to the form which will subscribe text boxes to this event handler to automatically take care of the formatting. The first one is called only once when the form is created, and takes care of any text boxes added at design time (or when the form is first created):
private void SubscribeCurrencyTextboxes(Control container)
{
foreach (Control control in container.Controls)
{
if (!(control is TextBox)) continue;
((TextBox)control).Leave += OnCurrencyTextBoxLeave;
}
}
To use this function we can simply call it within the form load event, or override OnLoad
as follows:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
SubscribeCurrencyTextboxes(this);
}
We should add one more function to subscribe to dynamically created text boxes at run time:
private void SubscribeCurrencyTextboxes(params TextBox[] textBoxes)
{
foreach (var textBox in textBoxes) textBox.Leave += OnCurrencyTextBoxLeave;
}
Now, when you dynamically create your text boxes, add another call to SubscribeCurrencyTextboxes
and supply it with a list of instances, such as:
SubscribeCurrencyTextboxes(textBox1, textBox2, ... textBox20);
When the user leaves each text box on the form, it will be formatted for currency automatically!
Another way (perhaps a better way) to achieve the same result -- especially if you require re-usability of this behavior -- would be to inherit from TextBox
and extend it. (Please see other answers here to your question suggesting the same.) We could call the inherited control CurrencyTextBox
and instead of dynamically adding ordinary text boxes to your form, you could add text boxes of this custom type.
To get you started, you could declare:
public class CurrencyTextBox : TextBox
{
// Apply currency formatting when text is set from code:
public override string Text
{
get { return base.Text; }
set
{
base.Text = Format(RemoveCurrencyFormatting(value));
}
}
// Expose decimal currency value to code:
public decimal Value
{
get { return this.value; }
set { this.value = value; }
}
private decimal value = 0m;
// Remove currency formatting dollar signs and commas on focus:
protected override void OnEnter(EventArgs e)
{
base.OnEnter(e);
this.Text = RemoveCurrencyFormatting(this.Text);
this.SelectAll();
}
// Apply currency formatting when focus is lost:
protected override void OnLeave(EventArgs e)
{
base.OnLeave(e);
Format(this.Text);
}
// Perform actual formatting:
private string Format(string text)
{
if (!decimal.TryParse(text, out this.value))
{
return value.ToString("C");
}
else return string.Empty;
}
// Remove currency formatting dollar signs and commas:
private string RemoveCurrencyFormatting(string value)
{
if (!string.IsNullOrEmpty(value))
{
return value
.Replace(NumberFormatInfo.CurrentInfo.CurrencySymbol, string.Empty)
.Replace(NumberFormatInfo.CurrentInfo.NumberGroupSeparator, string.Empty);
}
else return string.Empty;
}
}
This example makes use of NumberFormatInfo
to take care of currency symbols (such as dollar signs and thousands separator commas here in North America) which could trip up any type of currency formatting. Be sure to add a using
directive to System.Globalization:
using System.Globalization;
You can find out more information about NumberFormatInfo
on this MSDN page.