Как я могу заставить TextBox принимать только числовые значения в WinUI 3?

У меня есть TextBox, который я использую на странице настроек своего приложения. Теперь это текстовое поле должно принимать/отображать только цифры. Однако существует несколько примеров и решений этой проблемы, но ни одно из них не работает для WinUI 3, так как они в основном появились 5-10 лет назад.

KeyPress событие не существует в WinUI 3 TextBox. При поиске альтернатив я увидел событие KeyDown, однако аргументы этого события другие и KeyRoutedEventArgs не содержат никаких свойств, подобных KeyChar.

Пример кода, который я нашел, применим для приложений WPF:

private void txtbox1_KeyPress(object sender, KeyPressEventArgs e)
{
    if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar)) 
    {
        e.Handled = true;
    }
}

Как добиться такого поведения в WinUI 3 TextBox?

Ближайшим, вероятно, является NumberBox learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt/‌​… вы по-прежнему можете вводить недопустимые символы, но они будут удалены при смене фокуса. Исходник (WinUI2.8) находится здесь github.com/microsoft/microsoft-ui-xaml/tree/main/dev/NumberB‌​ox

Simon Mourier 09.12.2022 08:44
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
141
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете использовать InputScope!

Вы можете найти ссылку в документации Microsoft.

Вот пример от Microsoft:

<TextBox Header = "Telephone Number" InputScope = "TelephoneNumber"/>

Вы также можете выполнить дополнительные проверки в коде программной части, прослушивая событие TextChanged:

<TextBox TextChanged = "OnTextChanged" />

<!-- In your code-behind file -->

private void OnTextChanged(object sender, TextChangedEventArgs e)
{
    // Get the current text of the TextBox
    var text = ((TextBox)sender).Text;

    // Use a regular expression to only allow numeric values
    var regex = new Regex("^[0-9]*$");

    // If the text does not match the regular expression, undo the change
    if (!regex.IsMatch(text))
    {
        ((TextBox)sender).Undo();
    }
}


Редактировать:

В WinUI 3 вы также можете использовать событие KeyDown.

Это очень похоже на то, как вы это делали в WPF:

<TextBox KeyDown = "OnKeyDown" />

private void OnKeyDown(object sender, KeyRoutedEventArgs e)
{
    // Check if the key pressed is a numeric key
    if (!((e.Key >= VirtualKey.Number0 && e.Key <= VirtualKey.Number9) || (e.Key >= VirtualKey.NumberPad0 && e.Key <= VirtualKey.NumberPad9)))
    {
        // If the key is not numeric, cancel the event and prevent the key from being entered
        e.Handled = true;
    }
}

Спасибо за ответ. Пара вещей; Я установил InputScope на Digits, однако я все еще могу вводить буквы и символы, кроме цифр. После этого я попробовал ваше событие, однако это полностью удаляет поле, если введена нецифра. Если это первый символ, это нормально, однако, если, скажем, 124552a, он удаляет все содержимое, как это можно изменить, чтобы удалялся только последний введенный символ?

cptalpdeniz 09.12.2022 08:00

Привет Линк! Я только что попробовал ваш код события KeyDown, однако это не имело никакого эффекта (даже не удалял символы или эффект на поле), i.imgur.com/Ovn4ZOf.png

cptalpdeniz 10.12.2022 02:36

Обновлять. Теперь я использую событие TextChanging, которое происходит синхронно перед визуализацией текста. Это помогает с UX. Я работаю над исправлением проблемы «удаление всего текста вместо последней записи».

cptalpdeniz 10.12.2022 03:15
Ответ принят как подходящий

Ответ @Link Hylia был каким-то образом правильным для достижения запрошенного поведения. Я расширил это, на что ответил:

  1. Изменено используемое событие. События KeyDown или TextChanged были асинхронными событиями и не блокировали отображение введенного ввода на экране. Я изменил это на событие TextChanging, которое запускается синхронно и до рендеринга TextBox.Text. Используя этот метод, я могу контролировать текст до его рендеринга и улучшать UX.
  2. Вместо отмены я теперь просто удаляю введенный символ из текста и передаю его обратно в TextBox.
  3. Я вернул курсор туда, где он был раньше, чтобы пользователь мог продолжить печатать с того места, где он остановился.

Код можно найти ниже:

private void textBox1_TextChanging(TextBox sender, TextBoxTextChangingEventArgs args)
{
    var currentPosition = textBox1.SelectionStart - 1;
    var text = ((TextBox)sender).Text;
    
    var regex = new Regex("^[0-9]*$");

    if (!regex.IsMatch(text))
    {
        var foundChar = Regex.Match(textBox1.Text, @"[^0-9]");
        if (foundChar.Success)
        {
            textBox1.Text = textBox1.Text.Remove(foundChar.Index, 1);
        }
                
        textBox1.Select(currentPosition, 0);
    }
}

Да, это обходной путь. отличная работа.

Link Hylia 13.12.2022 13:05

Другие вопросы по теме