Десятичное текстовое поле в Windows Forms
Я работаю с приложением Financial Winforms и у меня возникли проблемы с управлением.
Мой клиент должен вставлять десятичные значения везде (цены, скидки и т. Д.), И я хотел бы избежать некоторых повторяющихся проверок.
Поэтому я сразу же попробовал MaskedTextBox, который бы соответствовал моим потребностям (с маской типа "€ 00000.00"), если бы не фокус и длина маски.
Я не могу предсказать, насколько большими будут цифры, которые мой клиент собирается ввести в приложение.
Я также не могу ожидать, что он начнет все с 00, чтобы добраться до запятой. Все должно быть дружественным к клавиатуре.
Я что-то упустил или просто нет способа (кроме написания пользовательского элемента управления) достичь этого с помощью стандартных элементов управления Windows Forms?
6 ответов
Эти два переопределенных метода сделали это для меня (отказ от ответственности: этот код еще не работает. Возможно, вам придется изменить)
protected override void OnKeyPress(KeyPressEventArgs e)
{
if (!char.IsNumber(e.KeyChar) & (Keys)e.KeyChar != Keys.Back
& e.KeyChar != '.')
{
e.Handled = true;
}
base.OnKeyPress(e);
}
private string currentText;
protected override void OnTextChanged(EventArgs e)
{
if (this.Text.Length > 0)
{
float result;
bool isNumeric = float.TryParse(this.Text, out result);
if (isNumeric)
{
currentText = this.Text;
}
else
{
this.Text = currentText;
this.Select(this.Text.Length, 0);
}
}
base.OnTextChanged(e);
}
Вам понадобится пользовательский элемент управления. Просто перехватите событие Validating в элементе управления и проверьте, может ли входная строка анализироваться как десятичное число.
Я не думаю, что вам нужен пользовательский элемент управления, просто напишите десятичный метод проверки для события проверки и используйте его для всех мест, которые вам нужно проверить. Не забудьте включить NumberFormatInfo, он будет работать с запятыми и знаками цифр.
Вам нужно только пропустить цифры и десятичные символы и избегать двойных десятичных символов. Кроме того, это автоматически добавляет 0 перед начальным десятичным числом.
public class DecimalBox : TextBox
{
protected override void OnKeyPress(KeyPressEventArgs e)
{
if (e.KeyChar == ',')
{
e.KeyChar = '.';
}
if (!char.IsNumber(e.KeyChar) && (Keys)e.KeyChar != Keys.Back && e.KeyChar != '.')
{
e.Handled = true;
}
if(e.KeyChar == '.' )
{
if (this.Text.Length == 0)
{
this.Text = "0.";
this.SelectionStart = 2;
e.Handled = true;
}
else if (this.Text.Contains("."))
{
e.Handled = true;
}
}
base.OnKeyPress(e);
}
}
Другой подход - заблокировать то, что вам не нужно, и отформатировать, когда вы закончите с этим.
class DecimalTextBox : TextBox
{
// Handle multiple decimals
protected override void OnKeyPress(KeyPressEventArgs e)
{
if (e.KeyChar == '.')
if (this.Text.Contains('.'))
e.Handled = true;
base.OnKeyPress(e);
}
// Block non digits
// I scrub characters here instead of handling in OnKeyPress so I can support keyboard events (ctrl + c/v/a)
protected override void OnTextChanged(EventArgs e)
{
this.Text = System.Text.RegularExpressions.Regex.Replace(this.Text, "[^.0-9]", "");
base.OnTextChanged(e);
}
// Apply our format when we're done
protected override void OnLostFocus(EventArgs e)
{
if (!String.IsNullOrEmpty(this.Text))
this.Text = string.Format("{0:N}", Convert.ToDouble(this.Text));
base.OnLostFocus(e);
}
}