TextBox WPF ввод только цифр

Все исходники / Язык программирования C# / OS Windows / Desktop / WPF программирование / TextBox WPF ввод только цифр
Оглавление:
  1. TextBox для ввода только цифр и чисел
  2. Класс TextBoxNumeric
  3. Метод OnPropertyChanged
  4. Возврат значения по умолчанию
  5. Событие OnLostFocus
  6. Методы фильтрации символов
  7. Достоинства и недостатки класса TextBoxNumeric
  8. Исходник класса TextBoxNumeric

TextBox для ввода только цифр и чисел

WPF TextBox ввод только чисел
Тестовая программа для класса TextBoxNumeric

TextBox WPF не имеет встроенных средств проверки ввода только чисел и в сети интернет всегда актуальна тема фильтрации ввода в текстовое поле только цифр. Просто замечательно, что модель ООП (Объектно-ориентированное программирования) дает нам возможность создания собственного класса с выводом чисел на основе существующего TextBox.

На данной странице описывается исходный код на C# одного из способов обеспечения корректности ввода цифр в элемент отображения и редактирования текста. Исходник оформлен в виде класса TextBoxNumeric производного от TextBox. В текстовое поле элемента TextBoxNumeric можно вводить только цифры и знаки пунктуации, формируя соответственно целые и дробные числа.

Класс TextBoxNumeric

Класс TextBoxNumeric имеет простой и небольшой по величине код, работающий достаточно эффективно. Логика TextBoxNumeric прекрасно справляется с посимвольным вводом и вставкой текста из буфера обмена. Поведение нового текстового поля формируют события изменения свойства зависимости TextProperty и потери фокуса LostFocus, в остальном TextBoxNumeric наследует все стандартные свойства TextBox.

Непосредственно проверка и коррекция ввода символов происходит в переопределенном обработчике события изменения свойств зависимостей
TextBox.OnPropertyChanged(DependencyPropertyChangedEventArgs e). Восстановление значения по умолчанию происходит в переопределенном обработчике события потери фокуса
TextBox. OnLostFocus(RoutedEventArgs e)

TextBoxNumeric имеет настроечные открытые свойства для определения их в программном коде и разметке XAML. Эти свойства подробно описываются в комментариях листинга структуры класса.

Структура программного кода класса TextBoxNumeric (методы описываются ниже):
public class TextBoxNumeric : TextBox
{
    #region Открытые свойства класса

    // Свойство хранит значение по умолчанию текста элемента
    private string _defaultValue = "0";
    public string DefaultValue
    {
        get { return _defaultValue; }
        set { _defaultValue = value; }
    }

    // Открытое свойство указывающее восстанавливать ли последнее значение
    // в случае полного удаления текста элемента.
    // Восстановление происходит при потере фокуса.
    private bool _restoreDefaultValue = false;
    public bool RestoreDefaultValue
    {
        get { return _restoreDefaultValue; }
        set { _restoreDefaultValue = value; }
    }

    // Вид десятичного разделителя
    char _decimalSeparator = '.';
    public char DecimalSeparator
    {
        get { return _decimalSeparator; }
        set { _decimalSeparator = value; }
    }


    // Вид текстового поля для ввода целых чисел,
    // или чисел с плавающей запятой.
    private bool _inputDouble = false;
    public bool InputDouble
    {
        get { return _inputDouble; }
        set { _inputDouble = value; }
    }

    #endregion

    #region События, формирующие функциональность числового текстового поля

    // Уведомление об изменениях свойств зависимости элемента TextBox.
    protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
        . . .
    }

    protected override void OnLostFocus(RoutedEventArgs e)
    {
        . . .
    }

    #endregion


    #region Фильтры ввода текста

    // Фильтр формирования корректного целого числа.
    private string FilterInteger(string inputText)
    {
        . . .
    }

    // Фильтр формирования корректного числа с дробной частью
    private string FilterFloat(string inputText)
    {
        . . .
    }

    #endregion
}

Метод OnPropertyChanged

Метод OnPropertyChanged вызывается при изменении любого свойства элемента TextBox. Отследить изменение только интересующего свойства зависимостей можно получая идентификатор свойства из аргументов, например:
if (e.Property == TextBox.TextProperty) {}.

В нашем случае нас интересует изменение свойства зависимости TextBox.TextProperty. В OnPropertyChanged изменение TextProperty отслеживается раньше, чем вызывается событие изменения введенного текста TextBox.TextChanged. Поэтому в теле метода OnPropertyChanged рационально разместить код фильтра ввода только цифр и свойство TextBox.Text будет получать готовую «оцифрованную» строку, без недопустимых символов.

Программный код метода TextBoxNumeric. OnPropertyChanged:
// Уведомление об изменениях свойств зависимости элемента TextBox.
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
    // Обязательный вызов базовой реализации.
    // Всегда вызывайте базовую реализацию первой операции.
    // Невыполнение этого требования приведет к значительному 
    // отключению всей системы свойств WPF,
    // что приведет к сообщению о неверных значениях.
    base.OnPropertyChanged(e);

    // Включаем работу кода только в контексте свойста Text элемента TextBox.
    if (e.Property == TextBox.TextProperty)
    {
        // Сопоставление шаблона с объявление новой локальной переменной:
        // проверка новое значение должно быть только типом string,
        // но не null или еще что-то. 
        if (e.NewValue is string newv == true)
        {
            // Если текстовое поле не пусто и есть изменения.
            if (Text != "" && newv.Equals(e.OldValue) == false)
            {
				// Выбор фильтра для коррекции ввода символов
                if (_inputDouble == false) Text = FilterInteger(newv);
                if (_inputDouble == true) Text = FilterFloat(newv);
            }
        }
    }
}

Возврат значения по умолчанию

Для некоторых приложений может понадобиться значение умолчанию, например, в случаях недопустимости пустой строки в TextBox, когда пользователь очистил строковое содержимое TextBox и перевел фокус на другой элемент. Очень возможно, что при запуске определённого действия в приложении может выброситься исключение, поскольку программный код ожидает число, но получает пустую строку.

В таких случаях и выручит значение по умолчанию. И ситуация уже будет выглядеть так: пользователь очистил текстовое поле, перевел фокус на другой элемент, а в текстовом поле восстановилось заранее определенное значение.

Для случаев, когда недопустимо пустое текстовое поле и наоборот, когда приложению требуется очистка TextBox в классе предусмотрена пара открытых свойств RestoreDefaultValue и DefaultValue (см. код структуры класса TextBoxNumeric выше).

Событие OnLostFocus

При переводе фокуса на другой визуальный элемент приложения в TextBox вызывается событие потери фокуса TextBox.LostFocus. Возврат значения по умолчанию организован в переопределённом обработчике события TextBoxNumeric.OnLostFocus. Данный программный код минимального объема и производит проверку разрешения возврата значения по умолчанию в пустой элемент TextBox.

Программный код обработчика события потери фокуса элементом TextBox:
protected override void OnLostFocus(RoutedEventArgs e)
{
    // Обязательный вызов базовой реализации.
    base.OnLostFocus(e);

    // Если разрешен вывод значения по умолчанию в пустое текстовое поле.
    if (Text == "" && RestoreDefaultValue == true)
    {
        // Теперь элемент TextBox содержит корректное числовое значение. 
        Text = _defaultValue;
    }
} 

Методы фильтрации символов

Методы FilterInteger(string inputText) и FilterFloat(string inputText) предназначены для удаления нецифровых (нечисловых) символов в текстовое поле TextBoxNumeric. После воздействия данных фильтров на вводимую пользователем строку формируются правильные текстовые целые числа и числа с дробной частью.

Фильтры построены на примитивной, но прекрасно работающей схеме посимвольной проверки строки и удаления первого нуля перед числом. Посимвольная проверка корректирует текст налету и не удаляет всю строку целиком из-за «неправильного» символа. Для экономии аппаратных ресурсов и повышения производительности строки формируются на основе экономичного класса StringBuilder.

Для обратной связи с пользователем при вводе «неправильного» символа в методах корректировки строк генерируется звук «недовольства» функцией Console.Beep(300, 100).

Программный код методов корректировки ввода числе в TextBoxNumeric:
// Фильтр формирования корректного целого числа.
private string FilterInteger(string inputText)
{
    StringBuilder res = new();
    bool onlyoneBeep = true;

    for (int i = 0; i < inputText.Length; i++)
    {
        // Фильтр ввода чисел, пропускает только числа (цифры).
        if (Char.IsDigit(inputText[i]) == true)
        {
            // Добавляем символ в строку результата.
            res.Append(inputText[i]);
        }
        else
        {
            // Недовольство звуком только один раз на всю новую строку или символ.
            if (onlyoneBeep == true)
            {
                onlyoneBeep = false;
                Console.Beep(300, 100);
            }
        }
    }

    // Удаление первого нуля, если количество цифр больше 1.
    if (res.Length > 1)
    {
        if (res[0] == '0')
        {
            res.Remove(0, 1);
        }
    }

    return res.ToString();
}

// Фильтр формирования корректного числа с дробной частью
private string FilterFloat(string inputText)
{
    StringBuilder res = new();
    bool onlyoneBeep = true;
    bool onlyonePunctuation = true;


    for (int i = 0; i < inputText.Length; i++)
    {
        // Фильтр ввода чисел, пропускает только числа (цифры).
        if (Char.IsDigit(inputText[i]) == true)
        {
            // Добавляем символ в строку результата.
            res.Append(inputText[i]);
        }
        else if (onlyonePunctuation == true &&
                Char.IsPunctuation(inputText[i]) == true)
        {
            // Добавляем символ в строку результата только один раз
            onlyonePunctuation = false;
            // Все виды разделителей заменяем на установленный.
            res.Append(_decimalSeparator);
        }
        else
        {
            // Недовольство звуком только один раз на всю новую строку или символ.
            if (onlyoneBeep == true)
            {
                onlyoneBeep = false;
                Console.Beep(300, 100);
            }
        }

    }

    // Удаление первого нуля, если за ним не следует разделитель.
    if (res.Length > 1)
    {
        if (res[0] == '0' && res[1] != _decimalSeparator)
        {
            res.Remove(0, 1);
        }
    }

    return res.ToString();
}

Достоинства и недостатки класса TextBoxNumeric

Достоинства работы кода TextBoxNumeric: перед событием изменения текста формируется правильно оцифрованная строка.
Недостатки: при каждом вводе проверяется весь текст заново.

На практическом уровне логика отбора цифр из вводимого в TextBoxNumeric текста работает очень быстро и безотказно, при посимвольном вводе и вставки строки из буфера обмена.

Исходник класса TextBoxNumeric

Исходный код класса TextBoxNumeric предоставляется как есть, не претендуя на идеальность, его можно изменять в соответствии со своими нуждами. TextBoxNumeric идет в составе приложения WPF для быстрого тестирования кода. Все что не описано на странице можно получить при тестировании приложения с текстовым полем для ввода чисел TextBoxNumeric. Исходник написан на языке C# WPF в MS Visual Studio 2022, платформа .NET6.

Скачать исходник

Тема: «TextBox WPF ввод только цифр» Язык программирования C# WpfTextBoxOnlyNumeric-vs17.zip Размер:125 КбайтЗагрузки:83