How to Create Numeric TextBox in C#

How to Create Numeric TextBox in C#

In this article we are going to create a numeric TextBox in C#.

Numeric TextBox in C# GitHub Link: DevInDeep/NumericTextBox (github.com)

What is Numeric TextBox?

Numeric TextBox is a more advanced version of the classic TextBox control. The main difference, is that it allows the user to enter values in a specific format. Such as: numeric, currency or percent. It should also support displaying values with custom units.

Well, it seems like we already have such control. Numeric Up/Down control allows the user to enter a predefined set of numbers. You can enter a number by using the Up/Down arrows. Or, simply typing the decimal value into the text field itself.

But, sometimes this is not enough. A real numeric TextBox control may come handy in a lot of situations. Entering currencies with specific format for example. A currency would consist of a decimal number prefixed with the currency sign. For example: $49.99. This is not possible with a Numeric Up/Down control.

Here is another example from the metric system: 170cm. This is the height of a person measured in centimeters. What if we want a control that can accept numbers followed by the measurement unit. As we stand right now, it seems like the Numeric Up/Down control is too limited in accepting only numbers. And, on the other hand, the TextBox is too general. It can accept all kinds of input.

What we actually need is a very specific control that can accept a limited user input. And, what’s more we need this control to be reusable, just like the TextBox. In this tutorial we are going to complete this task. We are going to create a Numeric TextBox control in C#.

Create Numeric TextBox Control in C#

More DevInDeep Tutorials:

Create Numeric TextBox in C#

First, let’s create a brand new Windows Forms App project. The language of choice should be set to C#. We are not going over the basic steps of creating a new project, because I assume you already know how to do that. So, we will dive right into the coding part.

Now, add a new C# class to your project and name it: NumericTextBox. Please note that this will be the name of the control as well. In the next section is the complete code listing for the Numeric TextBox.

public class NumericTextBox : TextBox
{
     public NumericTextBox()
     {
          this.KeyPress += NumericTextBox_KeyPress;
     }

     private void NumericTextBox_KeyPress(object sender, KeyPressEventArgs e)
     {
          if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && (e.KeyChar != '.'))
          {
               e.Handled = true;
          }
          
          if ((e.KeyChar == '.') && ((sender as TextBox).Text.IndexOf('.') > -1))
          {
               e.Handled = true;
          }
     }
}

First, let’s go over the inheritance part. In the beginning of this tutorial we mentioned why we can’t use TextBox control. It was too broad- too general for what we were looking for. But, it doesn’t mean that it is the wrong control. It is the right one, but we need to make it accept a more specific set of characters.

As a result, I decided to inherit from TextBox control. It has everything we need. It allows the user to enter an input. Now, we only need to write a C# code that will limit the user in what they are entering. If we want to accept integer and decimal numbers we need to change the default behavior of the control a little bit.

Numeric TextBox Comparison
Numeric UpDown vs Numeric TextBox

KeyPress Event Handler

In the constructor you can see that I am subscribing to the KeyPress event handler. It occurs when a character, space or backspace key is pressed, while the control is in focus. This event, when fired is accompanied with a KeyPressEventArgs object. This object provides data for the KeyPress event. It has two very important properties:

Handled Gets or sets a value indicating whether the KeyPress event was handled.
KeyChar Gets or sets the character corresponding to the key pressed.

Use the KeyChar property to sample keystrokes at run time and to consume or modify a subset of common keystrokes. In other words, this means that whenever a key is pressed, that particular character is stored in the KeyChar property. And, if everything is handled correctly, the character will appear in the TextBox, after the execution of this event.

The KeyPress event also allows us to decide if we want a certain character to appear in our custom Numeric TextBox. If we decide that a certain character is invalid, we can simply set the Handled property to True, and the TextBox won’t display it. And, that is why we decided to handle this event.

There are other events as well, such as: KeyDown and KeyUp. But, they do not offer the possibility of removing a character that doesn’t belong. In case you are interested, here is the order of how these events are fired, when a user presses a key:

  1. Key Down
  2. Key Press
  3. Key Up

Now, let’s take a deep dive into the rest of our C# code.

Code a TextBox that accepts only numeric values

Since, we already know how KeyPress event works, let’s dig deeper into the rest of the code.

if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && (e.KeyChar != '.'))
{
     e.Handled = true;
}

We saw earlier that, when a user presses a key, the KeyPress event will fire. As a result, a KeyPressEventArgs object is passed, in order to provide additional information. We need this object to process the key the user has pressed. As you can already imagine, we will use the KeyChar property.

Because our goal is to create a Numeric TextBox in C#, we need to set up some conditions. These conditional statements will decide whether or not a character the user has pressed will be accepted. Let’s elaborate the first If statement we are using.

First, we start with the IsControl method. It indicates whether a specified Unicode character is categorized as a control character (for example Backspace). After that we use IsDigit to check if a Unicode character is categorized as a decimal digit. At the end, we check if the character is a dot.

The important thing to note here is that all these conditions have negation next to them. Which means that we check if the key is not a control character and it is not a digit and it is not a dot sign. In a scenario like this we don’t want the TextBox control to show the character. That is why we set the Handled property to true.

TextBox that accepts numeric value with one decimal point

What we actually want is the very opposite of this scenario. We want to have a numeric value with one dot – which is optional. Correspondingly, the custom numeric TextBox will accept integer and a single decimal point numbers.

if ((e.KeyChar == '.') && ((sender as TextBox).Text.IndexOf('.') > -1))
{
     e.Handled = true;
}

The second code segment focuses on the dot character. First, we check if the user has entered the dot. Then we check if there already is another dot inside the numeric value. If indeed there is another one, the result of the IndexOf method will be different than -1. It will be 0 or greater. That indicates that the dot character is found at a certain position in the string. And the result this function produces tells us at which position this character appears.

This scenario is not something we want to happen. So, we make sure to set the Handled property to true. This way, the additional dot the user has entered won’t appear in the TextBox control.

If you want to know more about the IndexOf method exposed via the String class, you can read about it here. But the main thing you need to remember is the following definition:

Reports the zero-based index of the first occurrence of a specified Unicode character or string within this instance. The method returns -1 if the character or string is not found in this instance.

Microsoft Documentation

Numeric TextBox in C#, an alternative solution

If you want to create a numeric TextBox in C#, there are quite a few alternative solutions. Let’s review the C# code for something very simple, yet very effective. Here is the C# code listing:

private void NumericTextBox_KeyPress(object sender, KeyPressEventArgs e)
{
     if (!decimal.TryParse((sender as TextBox).Text+e.KeyChar, out decimal number))
          e.Handled = true;
}

As you can already see, we are once again handling the KeyPress event handler. But, this time we are handling it a little bit differently. This is a much simpler solution to the one we already presented above. It consists of only two C# statements.

The foundation for this code segment is the parsing part. You already know that you can parse strings in C# into different types. And we are going to use that to our advantage. We already stated our goal. Create a TextBox control that can only accept numeric values with a single decimal point. So, does this reminds of any particular type? If so, then let’s use it.

First, we will try to parse the string that is already inside the TextBox control. If the string can be parsed into a decimal type, then we can show the character a user has entered. But, if not, then we will simply omit it. As a result, we will get a Numeric TextBox control.

String Casting in C#

We already know that the Text property of a TextBox control, exposes the string, a user has already entered. In our case, we need to pick that string up, and try parse it into a decimal value. To do that we use the TryParse method. This is the definition offered by Microsoft:

Converts the string representation of a number to its Decimal equivalent. A return value indicates whether the conversion succeeded or failed.

Microsoft Documentation

This tells us that the method accepts a string and returns a bool value. The string we are passing is the one contained in the TextBox control. But, like we said earlier we decide which character will appear in the TextBox after the KeyPress event. So, we need to concatenate what we have currently in the TextBox with the currently pressed key.

If the TryParse function returns false, it means that the currently entered character combined with the Text property of the TextBox control is impossible to convert to a decimal number. On the other hand, if it returns true it means the string can be converted to a valid number and the currently pressed key can appear in the TextBox.

You can find more parsing examples here.

Numeric TextBox in C# using Regex

You have many different options when it comes to creating this control. Let’s go over one more. But, this time we are going to be using Regex. Because, it will allow us to validate the user input. For this example to work, I do assume that you have basic understanding of Regex. But, even if you do not, you can simply take over my solution as is.

Let’s look at the C# code listing:

private void NumericTextBox_KeyPress(object sender, KeyPressEventArgs e)
{
     if (!Regex.IsMatch((sender as TextBox).Text + e.KeyChar, @"^[1-9]\d*[.]?(\d+)?$"))
          e.Handled = true;
}

There are many ways how we can restructure this C# code to be more readable. But, for the purposes of this tutorial it is good enough.

Again, we are handling the KeyPress event. Inside we are concatenating the Text property of the control with the newly entered character (that is available inside the KeyChar property). Then, we will evaluate the result string via the IsMatch regex function.

If we look at the Microsoft documentation, we can conclude that this method will return true, only if the Regex engine finds a match in the input string. And, as you can see, we are matching for a decimal numeric value with one, or zero dot characters.

But, we set the Handled property to true, only if the Regex engine doesn’t match the pattern to the input string. As a result, we have another way of creating a Numeric TextBox in C# using Regex.

Numeric TextBox using Regex
Numeric TextBox using Regex pattern matching

Conclusion

You are free to choose any of these approaches. All of them are capable of limiting a TextBox to accept only decimal numbers. But the point to this tutorial goes beyond creating a Numeric TextBox in C#. It shows you how to handle user input, and how to limit and confine a control to accept only certain characters.

Now, it’s your turn. You can create a control that accepts a person’s height in centimeters. Or, you can create a control that accepts a currency numeric combined with the currency type as well. Try and experiment to see what everything is possible by handling the KeyPress event.