Создание маски и ограничение ввода символов в TextBox?

129
29 октября 2021, 11:20

Возникла необходимость создать ограничение для ввода данных в textBox.

Нужно вводить только цифры и буквы латиницей от A до F. В общем для ввода значений в шестнадцатеричной системе. Максимум можно ввести значение 4 байт и между ними автопробел.

Посмотрел реализации, но единого верного решения не нашел. Подскажите вариант как реализовать задуманное, необязательно адаптировать код под мой случай, хотелось бы увидеть саму суть реализации.

Answer 1

Например, можно реализовать это так:

public class HexTextBox : TextBox
{
    public HexTextBox()
    {
        DataObject.AddPastingHandler(this, Pasting);
    }
    protected override void OnPreviewKeyDown(KeyEventArgs e)
    {
        base.OnPreviewKeyDown(e);
        if (e.Key != Key.Space) return;
        if (IsValidInput(GetText(" "))) return;
        SystemSounds.Beep.Play();
        e.Handled = true;
    }
    protected override void OnPreviewTextInput(TextCompositionEventArgs e)
    {
        base.OnPreviewTextInput(e);
        if (IsValidInput(GetText(e.Text))) return;
        SystemSounds.Beep.Play();
        e.Handled = true;
    }
    private void Pasting(object sender, DataObjectPastingEventArgs e)
    {
        if (e.DataObject.GetDataPresent(typeof(string)))
        {
            var pastedText = (string)e.DataObject.GetData(typeof(string));
            if (IsValidInput(GetText(pastedText))) return;
        }
        SystemSounds.Beep.Play();
        e.CancelCommand();
    }
    private string GetText(string input)
    {
        int selectionStart = SelectionStart;
        if (Text.Length < selectionStart)
            selectionStart = Text.Length;
        int selectionLength = SelectionLength;
        if (Text.Length < selectionStart + selectionLength)
            selectionLength = Text.Length - selectionStart;
        var realtext = Text.Remove(selectionStart, selectionLength);
        int caretIndex = CaretIndex;
        if (realtext.Length < caretIndex)
            caretIndex = realtext.Length;
        var newtext = realtext.Insert(caretIndex, input);
        return newtext;
    }
    private bool IsValidInput(string input)
    {
        return input.All(c => "0123456789ABCDEF".Contains(c));
    }
}

OnPreviewTextInput обрабатывает весь ввод, кроме пробела (почему?), поэтому для обработки пробела придется еще и переопределить OnPreviewKeyDown. Вставку (из буфера обмена) обрабатывает Pasting. Вспомогательный метод GetText формирует выходную строку (ту, что получится, если входные символы будут приняты), возможно он здесь избыточен, т.к. у нас по идее принимаемые символы не зависят от позиции их ввода, но я делаю этот контрол на основе имеющегося у меня контрола для ввода числовых значений и там без него не обойтись. Ну и IsValidInput лишь проверяет корректна ли будет итоговая строка если пропустить ввод.

READ ALSO
C# пространства имен

C# пространства имен

Решение содержит следующую структуру:

79
C# WPF Интегрирование элементов в Xaml

C# WPF Интегрирование элементов в Xaml

Есть основное окно MainWindowxaml

147
Передаю команде Frame в WPF, но не работает

Передаю команде Frame в WPF, но не работает

Проблема в чем: мне нужно передать команде параметр в виде FrameFrame определён в коде XAML

98
C# WPF Задание фона формы из ресурса проекта

C# WPF Задание фона формы из ресурса проекта

разрабатываю приложение, но мне необходимо из ресурсов достать изображение по средством языка C# без xamlXAML не подходит из-за того, что в будущем...

246