Click here to Skip to main content
15,881,641 members
Articles / Desktop Programming / Windows Forms

A Currency-Masked TextBox from TextBox Class

Rate me:
Please Sign up or sign in to vote.
4.63/5 (6 votes)
7 Sep 2011CPOL4 min read 90.6K   4.7K   17   12
This is an useful control that masks the input text with currency symbol and thousands and decimals separators.

Introduction

In some applications we need to show the input text in a TextBox with some mask, like, for example, a currency mask to make it more easy to read and understand. In my case, I needed to put text, and additionally, the currency symbol, once the text was written. To do that, I decided to develop a control that inherits from the original TextBox control and implements some new members to allow the control to validate and show the input text with the currency mask we need.

Background

Here is a brief explanation...

TextBox (System.Windows.Forms.TextBox)

The TextBox control is one of the basic and most used controls in WinForms applications that allows the user to input text to interact with the application. It has basics behaviors and members that allow us to use it instantly without having to add anything to the control.

Based on the TextBox control, we are going to develop a TextBox that can mask our input text with currency format, including the currency symbol that we want.

Inheritance

Inheritance is a way to compartmentalize and reuse code by creating objects that have attributes and behaviors that can be based on previously created objects.

Inheritance allows us to work with simple controls like TextBox by taking advantage of their basic behaviors and lets us improve the control by adding new members to control some behaviors that we need to.

In Visual C#, we can write a class definition that inherits from TextBox like this:

C#
public partial class customTextBox : System.Windows.Forms.TextBox

Method overriding

It's a feature that allows a child class to provide a specific implementation of a method that's already provided by its parent class.

As an example, in Visual C#, we can override a method from a parent class by writing:

C#
protected override void OnLostFocus(EventArgs e)
{
    this.Text = formatText();
    base.OnLostFocus(e);
}

Development

Here is an explanation of the code behind the currencyTextBox:

The currencyTextBox control library

The Control Library JRINCCustomControls only contains the currencyTextBox control, and you can add this to your ToolBox in Visual Studio:

...or can reference it as a DLL component directly in your project:

The demo project

The demo project will show you how to implement the currencyTextBox control in a WinForms project, where you can test anything you want about the control.

The code

Now I'll explain the different members I've added to the new textbox and how they work.

In the currencyTextBox class in the JRINCCustomControls project are various custom members that help us achieve the goal of putting the currency-mask to our input text. These are:

Public properties

WorkingText (public string)

It's a read only property that contains our "working text". That means that it contains exactly what the user typed in the TextBox, the text without any mask or formatting.

Definition:

C#
private string _workingText;

public string WorkingText
{
    get { return _workingText; }
    private set { _workingText = value; }
}

PreFix (public string)

It's a public property that can be assigned and retrieved. It must contain the prefix or currency symbol that we want to precede the input text with. If empty, no prefix is used on the masked text. It can be assigned through the Properties window at design time.

Default value: Empty.

Definition:

C#
private string _preFix;
 
/// <summary>
/// Contains the prefix that preceed the inputted text.
/// </summary>
public string PreFix
{
    get { return _preFix; }
    set { _preFix = value; }
}

ThousandsSeparator (public char)

It's a public property that can be assigned and retrieved. It must contain the separator symbol for thousands that we want our input text to show when masked. If empty, no thousands separator is used on the masked text. It can be assigned through the Properties window at design time.

Default value: ','.

Definition:

C#
private char _thousandsSeparator = ',';

/// <summary>
/// Contains the separator symbol for thousands.
/// </summary>
public char ThousandsSeparator
{
    get { return _thousandsSeparator; }
    set { _thousandsSeparator = value; }
  
}

DecimalsSeparator (public char)

It's a public property that can be assigned and retrieved. It must contain the separator symbol for decimals that we want our input text to show when masked. If empty, no decimal separator is used in the masked text. It can be assigned through the Properties window at design time.

Default value: '.'.

Definition:

C#
private char _decimalsSeparator = '.';

/// <summary>
/// Contains the separator symbol for decimals.
/// </summary>
public char DecimalsSeparator
{
    get { return _decimalsSeparator; }
    set { _decimalsSeparator = value; }
}

DecimalPlaces (public int)

It's a public property that can be assigned and retrieved. It must contain the total places for decimal values that we want our input text to show when masked. Minimum value is 0. It can be assigned through the Properties window at design time.

Default value: 2.

Definition:

C#
private int _decimalPlaces = 2;

/// <summary>
/// Indicates the total places for decimal values.
/// </summary>
public int DecimalPlaces
{
    get { return _decimalPlaces; }
    set { _decimalPlaces = value; }
}

Public methods

formatText (public method) returns string

It formats the entered text with the desired specifications. Returns a string with the masked text.

Definition:

C#
/// <summary>
/// Formats the entered text.
/// </summary>
/// <returns></returns>
public string formatText()
{
    this.WorkingText = this.Text.Replace(
      (_preFix != "") ? _preFix : " ", String.Empty).Replace(
      (_thousandsSeparator.ToString() != "") ? 
        _thousandsSeparator.ToString() : " ", String.Empty).Replace(
      (_decimalsSeparator.ToString() != "") ? 
        _decimalsSeparator.ToString() : " ", String.Empty).Trim();
    int counter = 1;
    int counter2 = 0;
    char[] charArray = this.WorkingText.ToCharArray();
    StringBuilder str = new StringBuilder();

    for (int i = charArray.Length - 1; i >= 0; i--)
    {
        str.Insert(0, charArray.GetValue(i));
        if (this.DecimalPlaces == 0 && counter == 3)
        {
            counter2 = counter;
        }
        
        if (counter == this.DecimalPlaces && i > 0)
        {
            if (_decimalsSeparator != Char.MinValue)
                str.Insert(0, _decimalsSeparator);
            counter2 = counter + 3;
        }
        else if (counter == counter2 && i > 0)
        {
            if (_thousandsSeparator != Char.MinValue)
                str.Insert(0, _thousandsSeparator);
            counter2 = counter + 3;
        }
        counter = ++counter;
    }
    return (this._preFix != "" && str.ToString() != "") ? 
       _preFix + " " + str.ToString() : 
       (str.ToString() != "") ? str.ToString() : "";
}

Protected overridden methods

OnLostFocus (protected override method)

This method allows the currencyTextBox to load the formatted text to the Text property. It executes the formatText method, then proceeds to execute the original implementation of the OnLostFocus method.

Definition:

C#
protected override void OnLostFocus(EventArgs e)
{
    this.Text = formatText();
    base.OnLostFocus(e);
}

OnGotFocus (protected override method)

This method allows the currencyTextBox to load the working text to the Text property. In this state, the control is in edit mode (please refer to the WorkingText property definition above). After this, it proceeds to execute the original implementation of the OnGotFocus method.

Definition:

C#
protected override void OnGotFocus(EventArgs e)
{
    this.Text = this.WorkingText;
    base.OnGotFocus(e);
}

OnKeyPress (protected override method)

This method brings some validation to ensure that the values entered to the TextBox are only numbers. After the validation, it executes the original implementation of the OnKeyPress method.

Definition:

C#
protected override void OnKeyPress(KeyPressEventArgs e)
{
    if (!Char.IsDigit(e.KeyChar))
    {
        if (!(e.KeyChar == Convert.ToChar(Keys.Back)))
            e.Handled = true;
    }
    base.OnKeyPress(e);
}

Conclusion

There are so many characteristics that we can improve about a control like TextBox, and one of the more important things that we can do is always search for a way to improve it and make it more maintainable by adding reusable components like the CurrencyTextBox. I hope it can help you, like it did for me.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Venezuela Venezuela
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Gun Gun Febrianza2-Jun-16 17:17
Gun Gun Febrianza2-Jun-16 17:17 
QuestionNegative numbers Pin
Member 1239730626-Apr-16 3:40
Member 1239730626-Apr-16 3:40 
QuestionHelp Pin
aldo hexosa22-Apr-15 12:16
professionalaldo hexosa22-Apr-15 12:16 
AnswerRe: Help Pin
JRINC23-Apr-15 18:45
JRINC23-Apr-15 18:45 
QuestionAccounting application - needs to handle negative money amounts (such as debts and liabilities) Pin
Brian C Hart6-Dec-14 5:08
professionalBrian C Hart6-Dec-14 5:08 
AnswerRe: Accounting application - needs to handle negative money amounts (such as debts and liabilities) Pin
JRINC23-Apr-15 18:48
JRINC23-Apr-15 18:48 
QuestionCurrency-Masked TextBox - Good job! Pin
Nanox1126-Dec-13 4:45
Nanox1126-Dec-13 4:45 
AnswerRe: Currency-Masked TextBox - Good job! Pin
JRINC26-Dec-13 8:01
JRINC26-Dec-13 8:01 
SuggestionSource doesn't match article Pin
LH40530-Jul-13 5:01
LH40530-Jul-13 5:01 
The source code available for download doesn't match the article.
For example, the prefix property is missing.
Perhaps the source is an older version?
GeneralRe: Source doesn't match article Pin
JRINC2-Sep-13 5:11
JRINC2-Sep-13 5:11 
QuestionRegional settings values Pin
Benny Tordrup17-Sep-11 1:20
Benny Tordrup17-Sep-11 1:20 
AnswerRe: Regional settings values Pin
JRINC19-Sep-11 2:53
JRINC19-Sep-11 2:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.