Part of the power that .NET and C# give you is the ability to sub-class the built-in Controls, and make them behave the way you want.
Usually, you'll add a Component to your WinForms Project, and then modify the declaration of the Class Visual Studio generates for you so that you inherit from the Control you wish to modify. Consider this sub-classed TextBox that will accept only digits, and the backspace character:
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace YourNameSpace
{
public partial class DigitOnlyTextBox : TextBox
{
public DigitOnlyTextBox()
{
InitializeComponent();
}
public DigitOnlyTextBox(IContainer container)
{
container.Add(this);
InitializeComponent();
AcceptsReturn = false;
AcceptsTab = false;
Multiline = false;
}
private char backspace = Convert.ToChar(Keys.Back);
protected override void OnKeyPress(KeyPressEventArgs e)
{
char key = e.KeyChar;
if (Char.IsDigit(key) || key == backspace)
{
base.OnKeyPress(e);
}
else
{
e.Handled = true;
}
}
}
}
Now where things get "tricky" are when you want to prevent the user from doing things like:
1. if you are allowing periods: stop the user from entering more than one period, and stop the user from putting a period at start, or end, of the string.
2. if you are allowing commas: stop the user from leaving a comma at the beginning, or end, of the string
3. entering two or more periods, or commas, in a row
And, what about the user possibly pasting in content on the Clipboard into the TextBox ?
The possible complexity of the code handling what the user inputs, and making sure the input is acceptable is one reason many people just use the NumericUpDownControl in WinForms. Or, use a MaskedTextBox with a custom RegEx.