Мне пришлось реализовать элемент управления, который принимает только числа, целые или действительные числа.
Я создаю элемент управления как специализацию (читай: производную от) элемента управления TextBox, и использую элемент управления вводом и регулярное выражение для проверки.
Добавление проверки диапазона очень просто.
Это код для построения регулярного выражения. _numericSeparation - строка с символами, принятыми в качестве десятичных значений запятой
(например, «.» или «,»: $ 10,50 10,50 €
private string ComputeRegexPattern()
{
StringBuilder builder = new StringBuilder();
if (this._forcePositives)
{
builder.Append("([+]|[-])?");
}
builder.Append(@"[\d]*((");
if (!this._useIntegers)
{
for (int i = 0; i < this._numericSeparator.Length; i++)
{
builder.Append("[").Append(this._numericSeparator[i]).Append("]");
if ((this._numericSeparator.Length > 0) && (i != (this._numericSeparator.Length - 1)))
{
builder.Append("|");
}
}
}
builder.Append(@")[\d]*)?");
return builder.ToString();
}
Регулярное выражение сопоставляет любое число (то есть любую строку с числовыми символами) только с одним символом в качестве разделения чисел и необязательным символом «+» или «-» в начале строки.
После создания регулярного выражения (при создании экземпляра элемента управления) вы проверяете правильность значения, переопределяя метод OnValidating.
CheckValidNumber () просто применяет регулярное выражение к введенному тексту. Если совпадение с регулярным выражением завершается неудачно, активируется поставщик ошибок с указанной ошибкой (устанавливается с помощью общего свойства ValidationError) и возникает событие ValidationError.
Здесь вы можете выполнить проверку, чтобы узнать, находится ли номер в требуемом диапазоне.
private bool CheckValidNumber()
{
if (Regex.Match(this.Text, this.RegexPattern).Value != this.Text)
{
this._errorProvider.SetError(this, this.ValidationError);
return false;
}
this._errorProvider.Clear();
return true;
}
protected override void OnValidating(CancelEventArgs e)
{
bool flag = this.CheckValidNumber();
if (!flag)
{
e.Cancel = true;
this.Text = "0";
}
base.OnValidating(e);
if (!flag)
{
this.ValidationFail(this, EventArgs.Empty);
}
}
Как я уже сказал, я также запрещаю пользователю вводить данные в текстовое поле, кроме числовых символов, переопределяющих метод OnKeyPress:
protected override void OnKeyPress(KeyPressEventArgs e)
{
if ((!char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar)) && (!this._numberSymbols.Contains(e.KeyChar.ToString()) && !this._numericSeparator.Contains(e.KeyChar.ToString())))
{
e.Handled = true;
}
if (this._numberSymbols.Contains(e.KeyChar.ToString()) && !this._forcePositives)
{
e.Handled = true;
}
if (this._numericSeparator.Contains(e.KeyChar.ToString()) && this._useIntegers)
{
e.Handled = true;
}
base.OnKeyPress(e);
}
Элегантный штрих: я проверяю, является ли число действительным каждый раз, когда пользователь отпускает клавишу, чтобы пользователь мог получать отзывы при вводе. (Но помните, что вы должны быть осторожны с событием ValidationFail;))
protected override void OnKeyUp(KeyEventArgs e)
{
this.CheckValidNumber();
base.OnKeyUp(e);
}