I\'m looking to accept digits and the decimal point, but no sign.
I\'ve looked at samples using the NumericUpDown control for Windows Forms, and this sample of a Num
Here is my version of it. It's based on a base ValidatingTextBox
class that just undoes what has been done if it's not "valid". It supports paste, cut, delete, backspace, +, - etc.
For 32-bit integer, there is a Int32TextBox class that just compares with an int. I have also added floating point validation classes.
public class ValidatingTextBox : TextBox
{
private bool _inEvents;
private string _textBefore;
private int _selectionStart;
private int _selectionLength;
public event EventHandler ValidateText;
protected override void OnPreviewKeyDown(KeyEventArgs e)
{
if (_inEvents)
return;
_selectionStart = SelectionStart;
_selectionLength = SelectionLength;
_textBefore = Text;
}
protected override void OnTextChanged(TextChangedEventArgs e)
{
if (_inEvents)
return;
_inEvents = true;
var ev = new ValidateTextEventArgs(Text);
OnValidateText(this, ev);
if (ev.Cancel)
{
Text = _textBefore;
SelectionStart = _selectionStart;
SelectionLength = _selectionLength;
}
_inEvents = false;
}
protected virtual void OnValidateText(object sender, ValidateTextEventArgs e) => ValidateText?.Invoke(this, e);
}
public class ValidateTextEventArgs : CancelEventArgs
{
public ValidateTextEventArgs(string text) => Text = text;
public string Text { get; }
}
public class Int32TextBox : ValidatingTextBox
{
protected override void OnValidateText(object sender, ValidateTextEventArgs e) => e.Cancel = !int.TryParse(e.Text, out var value);
}
public class Int64TextBox : ValidatingTextBox
{
protected override void OnValidateText(object sender, ValidateTextEventArgs e) => e.Cancel = !long.TryParse(e.Text, out var value);
}
public class DoubleTextBox : ValidatingTextBox
{
protected override void OnValidateText(object sender, ValidateTextEventArgs e) => e.Cancel = !double.TryParse(e.Text, out var value);
}
public class SingleTextBox : ValidatingTextBox
{
protected override void OnValidateText(object sender, ValidateTextEventArgs e) => e.Cancel = !float.TryParse(e.Text, out var value);
}
public class DecimalTextBox : ValidatingTextBox
{
protected override void OnValidateText(object sender, ValidateTextEventArgs e) => e.Cancel = !decimal.TryParse(e.Text, out var value);
}
Note 1: When using WPF binding, you must make sure you use the class that fits the bound property type otherwise, it may lead to strange results.
Note 2: When using floating point classes with WPF binding, make sure the binding uses the current culture to match the TryParse method I've used.