Как сделать текстовое поле, которое принимает только цифры? - PullRequest
535 голосов
/ 21 января 2009

У меня есть приложение Windows Forms с элементом управления textbox, которое я хочу принимать только целочисленные значения. В прошлом я делал такую ​​проверку, перегружая событие KeyPress и просто удаляя символы, которые не соответствовали спецификации. Я посмотрел на элемент управления MaskedTextBox, но мне хотелось бы более общего решения, которое могло бы работать с, возможно, регулярным выражением или зависеть от значений других элементов управления.

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

Ответы [ 34 ]

4 голосов
/ 11 мая 2016

На нашей веб-странице с определением текстового поля мы можем добавить событие onkeypress для приема только чисел. Оно не будет отображать никаких сообщений, но предотвратит неправильный ввод. У меня это сработало, пользователь не мог ничего ввести, кроме номера.

<asp:TextBox runat="server" ID="txtFrom"
     onkeypress="if(isNaN(String.fromCharCode(event.keyCode))) return false;">
4 голосов
/ 28 ноября 2017

Просто используйте элемент управления NumericUpDown и установите видимость этих уродливых кнопок вверх-вниз на false.

numericUpDown1.Controls[0].Visible = false;

NumericUpDown на самом деле представляет собой набор элементов управления, содержащий «вращающееся окно» (кнопки вверх-вниз), текстовое поле и некоторый код для проверки и объединения всех этих элементов.

Маркировка:

YourNumericUpDown.Controls[0].visible = false 

будет скрывать кнопки, оставляя основной код активным.

Хотя это и не очевидное решение, оно простое и эффективное. .Controls[1] будет скрывать часть текстового поля, если вы захотите сделать это вместо этого.

4 голосов
/ 21 января 2009

Я сделал что-то для этого на CodePlex .

Он работает, перехватывая событие TextChanged. Если результат будет хорошим числом, он будет сохранен. Если что-то не так, последнее хорошее значение будет восстановлено. Источник слишком велик для публикации здесь, но здесь - ссылка на класс , который обрабатывает ядро ​​этой логики.

2 голосов
/ 21 января 2009

Взгляните на Обработка ввода в WinForm

Я разместил свое решение, которое использует события ProcessCmdKey и OnKeyPress в текстовом поле. В комментариях показано, как использовать регулярные выражения для проверки нажатия клавиш и соответствующего блокирования / разрешения.

2 голосов
/ 19 июня 2018

Используя подход, описанный в Ответ Фабио Иотти Я создал более общее решение:

public abstract class ValidatedTextBox : TextBox {
    private string m_lastText = string.Empty;
    protected abstract bool IsValid(string text);
    protected sealed override void OnTextChanged(EventArgs e) {
        if (!IsValid(Text)) {
            var pos = SelectionStart - Text.Length + m_lastText.Length;
            Text = m_lastText;
            SelectionStart = Math.Max(0, pos);
        }
        m_lastText = Text;
        base.OnTextChanged(e);
    }
}

«ValidatedTextBox», который содержит все нетривиальные действия проверки. Все, что осталось сделать, это наследовать от этого класса и переопределить метод "IsValid" любой необходимой логикой проверки. Например, используя этот класс, можно создать «RegexedTextBox», который будет принимать только строки, которые соответствуют определенному регулярному выражению:

public abstract class RegexedTextBox : ValidatedTextBox {
    private readonly Regex m_regex;
    protected RegexedTextBox(string regExpString) {
        m_regex = new Regex(regExpString);
    }
    protected override bool IsValid(string text) {
        return m_regex.IsMatch(Text);
    }
}

После этого, наследуя от класса «RegexedTextBox», мы можем легко создавать элементы управления «PositiveNumberTextBox» и «PositiveFloatingPointNumberTextBox»:

public sealed class PositiveNumberTextBox : RegexedTextBox {
    public PositiveNumberTextBox() : base(@"^\d*$") { }
}

public sealed class PositiveFloatingPointNumberTextBox : RegexedTextBox {
    public PositiveFloatingPointNumberTextBox()
        : base(@"^(\d+\" + CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator + @")?\d*$") { }
}
2 голосов
/ 21 января 2009

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

2 голосов
/ 24 июля 2014

Кажется, что многие из текущих ответов на этот вопрос вручную анализируют входной текст. Если вы ищете определенный встроенный числовой тип (например, int или double), почему бы просто не делегировать работу методу TryParse этого типа? Например:

public class IntTextBox : TextBox
{
    string PreviousText = "";
    int BackingResult;

    public IntTextBox()
    {
        TextChanged += IntTextBox_TextChanged;
    }

    public bool HasResult { get; private set; }

    public int Result
    {
        get
        {
            return HasResult ? BackingResult : default(int);
        }
    }

    void IntTextBox_TextChanged(object sender, EventArgs e)
    {
        HasResult = int.TryParse(Text, out BackingResult);

        if (HasResult || string.IsNullOrEmpty(Text))
        {
            // Commit
            PreviousText = Text;
        }
        else
        {
            // Revert
            var changeOffset = Text.Length - PreviousText.Length;
            var previousSelectionStart =
                Math.Max(0, SelectionStart - changeOffset);

            Text = PreviousText;
            SelectionStart = previousSelectionStart;
        }
    }
}

Если вы хотите что-то более общее, но все же совместимое с Visual Studio Designer:

public class ParsableTextBox : TextBox
{
    TryParser BackingTryParse;
    string PreviousText = "";
    object BackingResult;

    public ParsableTextBox()
        : this(null)
    {
    }

    public ParsableTextBox(TryParser tryParse)
    {
        TryParse = tryParse;

        TextChanged += ParsableTextBox_TextChanged;
    }

    public delegate bool TryParser(string text, out object result);

    public TryParser TryParse
    {
        set
        {
            Enabled = !(ReadOnly = value == null);

            BackingTryParse = value;
        }
    }

    public bool HasResult { get; private set; }

    public object Result
    {
        get
        {
            return GetResult<object>();
        }
    }

    public T GetResult<T>()
    {
        return HasResult ? (T)BackingResult : default(T);
    }

    void ParsableTextBox_TextChanged(object sender, EventArgs e)
    {
        if (BackingTryParse != null)
        {
            HasResult = BackingTryParse(Text, out BackingResult);
        }

        if (HasResult || string.IsNullOrEmpty(Text))
        {
            // Commit
            PreviousText = Text;
        }
        else
        {
            // Revert
            var changeOffset = Text.Length - PreviousText.Length;
            var previousSelectionStart =
                Math.Max(0, SelectionStart - changeOffset);

            Text = PreviousText;
            SelectionStart = previousSelectionStart;
        }
    }
}

И, наконец, если вы хотите что-то полностью общее и не заботитесь о поддержке Designer:

public class ParsableTextBox<T> : TextBox
{
    TryParser BackingTryParse;
    string PreviousText;
    T BackingResult;

    public ParsableTextBox()
        : this(null)
    {
    }

    public ParsableTextBox(TryParser tryParse)
    {
        TryParse = tryParse;

        TextChanged += ParsableTextBox_TextChanged;
    }

    public delegate bool TryParser(string text, out T result);

    public TryParser TryParse
    {
        set
        {
            Enabled = !(ReadOnly = value == null);

            BackingTryParse = value;
        }
    }

    public bool HasResult { get; private set; }

    public T Result
    {
        get
        {
            return HasResult ? BackingResult : default(T);
        }
    }

    void ParsableTextBox_TextChanged(object sender, EventArgs e)
    {
        if (BackingTryParse != null)
        {
            HasResult = BackingTryParse(Text, out BackingResult);
        }

        if (HasResult || string.IsNullOrEmpty(Text))
        {
            // Commit
            PreviousText = Text;
        }
        else
        {
            // Revert
            var changeOffset = Text.Length - PreviousText.Length;
            var previousSelectionStart =
                Math.Max(0, SelectionStart - changeOffset);

            Text = PreviousText;
            SelectionStart = previousSelectionStart;
        }
    }
}
2 голосов
/ 01 декабря 2017

Должны быть приняты как целые числа, так и числа с плавающей запятой, включая отрицательные числа.

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    // Text
    string text = ((Control) sender).Text;

    // Is Negative Number?
    if (e.KeyChar == '-' && text.Length == 0)
    {
        e.Handled = false;
        return;
    }

    // Is Float Number?
    if (e.KeyChar == '.' && text.Length > 0 && !text.Contains("."))
    {
        e.Handled = false;
        return;
    }

    // Is Digit?
    e.Handled = (!char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar));
}
2 голосов
/ 05 января 2014

Привет, ты можешь сделать что-то подобное в событии textaged текстового поля.

вот демка

    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        string actualdata = string.Empty;
        char[] entereddata = textBox1.Text.ToCharArray();
        foreach (char aChar in entereddata.AsEnumerable())
        {
            if (Char.IsDigit(aChar))
            {
                actualdata = actualdata + aChar;
                // MessageBox.Show(aChar.ToString());
            }
            else
            {
                MessageBox.Show(aChar + " is not numeric");
                actualdata.Replace(aChar, ' ');
                actualdata.Trim();
            }
        }
        textBox1.Text = actualdata;
    }
2 голосов
/ 16 октября 2013
private void txt3_KeyPress(object sender, KeyPressEventArgs e)
{
    for (int h = 58; h <= 127; h++)
    {
        if (e.KeyChar == h)             //58 to 127 is alphabets tat will be         blocked
        {
            e.Handled = true;
        }
    }
    for(int k=32;k<=47;k++)
    {
        if (e.KeyChar == k)              //32 to 47 are special characters tat will 
        {                                  be blocked
            e.Handled = true;
        }
    }
}

попробуйте это очень просто

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...