Как сделать текстовое поле, которое принимает только цифры?

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

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

20.01.2009 21:55:01
цифры или цифры? большая разница: даже целые числа могут стать отрицательными
Joel Coehoorn 20.01.2009 21:59:16
Вопрос был предназначен для чисел, включая весь набор рациональных чисел.
Mykroft 7.06.2009 23:01:03
30 ОТВЕТОВ
РЕШЕНИЕ

Два варианта:

  1. Используйте NumericUpDownвместо. NumericUpDown делает фильтрацию за вас, что приятно. Конечно, это также дает вашим пользователям возможность нажимать стрелки вверх и вниз на клавиатуре, чтобы увеличивать и уменьшать текущее значение.

  2. Обработайте соответствующие события клавиатуры, чтобы запретить что-либо, кроме числового ввода. Я имел успех с этими двумя обработчиками событий в стандартном TextBox:

    private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
    {
        if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) &&
            (e.KeyChar != '.'))
        {
                e.Handled = true;
        }
    
        // only allow one decimal point
        if ((e.KeyChar == '.') && ((sender as TextBox).Text.IndexOf('.') > -1))
        {
            e.Handled = true;
        }
    }

Вы можете удалить проверку '.'(и последующую проверку для более чем одного '.'), если ваш TextBox не должен разрешать десятичные разряды. Вы также можете добавить проверку, '-'если ваш TextBox должен разрешать отрицательные значения.

Если вы хотите ограничить пользователя количеством цифр, используйте: textBox1.MaxLength = 2; // this will allow the user to enter only 2 digits

790
14.10.2014 15:40:21
Единственным недостатком NumericUpDown является то, что он не обеспечивает обратной связи при вводе значения за пределами Максимального или Минимально допустимого значения - он просто меняет введенное вами значение. TextBox может по крайней мере разрешить недопустимые значения, чтобы вы могли предупредить пользователя при отправке формы.
Matt Hamilton 20.01.2009 22:12:36
Это правда - пользователь всегда может вставить некоторые нечисловые символы. Вы можете надеяться, что проверка формы поймает это, так как в какой-то момент вы захотите сделать Int32.TryParse или что-то еще.
Matt Hamilton 20.01.2009 22:41:41
Вам нужно будет приложить дополнительные усилия, чтобы глобализировать это, заменив проверки на «.» с проверками на CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator.
Jeff Yates 16.04.2009 18:08:06
@HamishGrubijan, IsControl не имеет ничего общего с управляющим ключом; возвращает, является ли символ контрольным. Допуская управляющие символы, вы не нарушаете такие вещи, как возврат, удаление или клавиши со стрелками
Thomas Levesque 31.10.2011 02:22:02
Между прочим, он все еще принимает недопустимый ввод ctrl + v; ошибка, которая даже существует в официальном элементе управления NumericUpDown.
Nyerguds 10.08.2015 22:33:00

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

2
20.01.2009 21:59:29

Попробуйте MaskedTextBox . Требуется простой формат маски, чтобы вы могли ограничить ввод цифрами, датами или чем-то еще.

13
20.01.2009 22:01:14
Я специально не хочу использовать MaskedTextBox. Форматы, которые они допускают, могут быть очень ограничивающими. Они работают для этого случая, но я хотел бы сделать что-то более общее.
Mykroft 20.01.2009 22:03:16

Я предполагаю, что из контекста и используемых вами тегов вы пишете приложение .NET C #. В этом случае вы можете подписаться на событие изменения текста и проверить каждое нажатие клавиши.

private void textBox1_TextChanged(object sender, EventArgs e)
{
    if (System.Text.RegularExpressions.Regex.IsMatch(textBox1.Text, "[^0-9]"))
    {
        MessageBox.Show("Please enter only numbers.");
        textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 1);
    }
}
51
31.10.2019 18:17:17
Разве это не даст очень странный эффект, если вы наберете в середине числа?
Colin Pickard 25.10.2010 19:14:01
а также должно быть:textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 1);
Pieniadz 24.08.2011 09:59:28
что если первый символ сам по себе не является цифрой ... не вычитал бы 1 в этом случае,
manu_dilip_shah 26.03.2012 08:29:53
Кроме того, использование TextChanged вместо KeyPress создает некоторую рекурсию в том, что код переходит во второе событие TextChanged после метода Remove.
WEFX 21.05.2013 14:29:04
Вы переключили входные параметры и параметры шаблона для вашей функции IsMatch. Сначала следует ввести данные, а затем шаблон. msdn.microsoft.com/en-us/library/sdx2bds0(v=vs.110).aspx
Mibou 17.02.2014 09:52:48

Посмотрите на обработку ввода в WinForm

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

2
23.05.2017 11:54:59

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

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

4
20.01.2009 22:18:13

И только потому, что всегда веселее делать вещи в одну строку ...

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

ПРИМЕЧАНИЕ. Это НЕ мешает пользователю копировать / вставлять в это текстовое поле. Это не безопасный способ очистки ваших данных.

148
20.01.2009 22:24:54
это не общие решения, так как оно работает только для интергеров. Я должен был реализовать такую ​​вещь недавно, и я закончил с попыткой парсинга результирующей строки в число и разрешил ввод, только если парсинг был
grzegorz_p 4.01.2012 15:03:25
Это может не работать, когда несколько методов обрабатывают KeyPressсобытия из одного и того же текстового поля. Для одного события может быть установлено e.Handledзначение true, а затем для другого может быть установлено значение false. В общем, лучше использоватьif (...) e.Handled = true;
Nathaniel Jones 27.05.2014 16:55:36
Вы можете отключить свойство ShortcutsEnabled, чтобы запретить копирование с помощью клавиатуры или меню
Ahmad 11.12.2014 13:25:44
HAHA! Да! Один лайнер!
Jamie L. 23.07.2015 18:20:48
Эх. TextChangedСобытие , которое проходит через это с регулярным выражением может исправить копипаст;)
Nyerguds 10.08.2015 22:34:06

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

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

В основном вы можете нажать только 0 - 9 и .

Вы можете иметь только один 0 до .

Все остальные символы игнорируются и позиция курсора сохраняется.

    private bool _myTextBoxChanging = false;

    private void myTextBox_TextChanged(object sender, EventArgs e)
    {
        validateText(myTextBox);
    }

    private void validateText(TextBox box)
    {
        // stop multiple changes;
        if (_myTextBoxChanging)
            return;
        _myTextBoxChanging = true;

        string text = box.Text;
        if (text == "")
            return;
        string validText = "";
        bool hasPeriod = false;
        int pos = box.SelectionStart;
        for (int i = 0; i < text.Length; i++ )
        {
            bool badChar = false;
            char s = text[i];
            if (s == '.')
            {
                if (hasPeriod)
                    badChar = true;
                else
                    hasPeriod = true;
            }
            else if (s < '0' || s > '9')
                badChar = true;

            if (!badChar)
                validText += s;
            else
            {
                if (i <= pos)
                    pos--;
            }
        }

        // trim starting 00s
        while (validText.Length >= 2 && validText[0] == '0')
        {
            if (validText[1] != '.')
            {
                validText = validText.Substring(1);
                if (pos < 2)
                    pos--;
            }
            else
                break;
        }

        if (pos > validText.Length)
            pos = validText.Length;
        box.Text = validText;
        box.SelectionStart = pos;
        _myTextBoxChanging = false;
    }

Вот быстро модифицированная версия int:

    private void validateText(TextBox box)
    {
        // stop multiple changes;
        if (_myTextBoxChanging)
            return;
        _myTextBoxChanging = true;

        string text = box.Text;
        if (text == "")
            return;
        string validText = "";
        int pos = box.SelectionStart;
        for (int i = 0; i < text.Length; i++ )
        {
            char s = text[i];
            if (s < '0' || s > '9')
            {
                if (i <= pos)
                    pos--;
            }
            else
                validText += s;
        }

        // trim starting 00s 
        while (validText.Length >= 2 && validText.StartsWith("00")) 
        { 
            validText = validText.Substring(1); 
            if (pos < 2) 
                pos--; 
        } 

        if (pos > validText.Length)
            pos = validText.Length;
        box.Text = validText;
        box.SelectionStart = pos;
        _myTextBoxChanging = false;
    }
1
31.10.2011 04:54:50
Это решение изобретает колесо с предостережениями. Локализация например.
Julien Guertault 8.05.2012 08:05:35
int Number;
bool isNumber;
isNumber = int32.TryPase(textbox1.text, out Number);

if (!isNumber)
{ 
    (code if not an integer);
}
else
{
    (code if an integer);
}
0
20.11.2011 05:35:22

Вы можете использовать TextChangedсобытие

private void textBox_BiggerThan_TextChanged(object sender, EventArgs e)
{
    long a;
    if (! long.TryParse(textBox_BiggerThan.Text, out a))
    {
        // If not int clear textbox text or Undo() last operation
        textBox_LessThan.Clear();
    }
}
12
5.11.2014 08:39:55
Похоже, это должно работать хорошо, если вы использовали Undo(), но это приводит к StackOverflowException.
Drew Chapin 19.10.2015 03:44:49
Похоже, что свойство TextChanged является частью процедуры, которую вы хотите отменить (). У меня есть переменная для всего окна, и я использую public int txtBoxValue, и если tryParse не работает, я возвращаю текст в txtBox путемtxtBox.Text = txtBoxValue.ToString();
L. Zeda 22.12.2016 08:41:29

Это может быть полезно. Он допускает «реальные» числовые значения, включая правильные десятичные точки и предшествующие знаки плюс или минус. Вызовите его из соответствующего события KeyPress.

       private bool IsOKForDecimalTextBox(char theCharacter, TextBox theTextBox)
    {
        // Only allow control characters, digits, plus and minus signs.
        // Only allow ONE plus sign.
        // Only allow ONE minus sign.
        // Only allow the plus or minus sign as the FIRST character.
        // Only allow ONE decimal point.
        // Do NOT allow decimal point or digits BEFORE any plus or minus sign.

        if (
            !char.IsControl(theCharacter)
            && !char.IsDigit(theCharacter)
            && (theCharacter != '.')
            && (theCharacter != '-')
            && (theCharacter != '+')
        )
        {
            // Then it is NOT a character we want allowed in the text box.
            return false;
        }



        // Only allow one decimal point.
        if (theCharacter == '.'
            && theTextBox.Text.IndexOf('.') > -1)
        {
            // Then there is already a decimal point in the text box.
            return false;
        }

        // Only allow one minus sign.
        if (theCharacter == '-'
            && theTextBox.Text.IndexOf('-') > -1)
        {
            // Then there is already a minus sign in the text box.
            return false;
        }

        // Only allow one plus sign.
        if (theCharacter == '+'
            && theTextBox.Text.IndexOf('+') > -1)
        {
            // Then there is already a plus sign in the text box.
            return false;
        }

        // Only allow one plus sign OR minus sign, but not both.
        if (
            (
                (theCharacter == '-')
                || (theCharacter == '+')
            )
            && 
            (
                (theTextBox.Text.IndexOf('-') > -1)
                ||
                (theTextBox.Text.IndexOf('+') > -1)
            )
            )
        {
            // Then the user is trying to enter a plus or minus sign and
            // there is ALREADY a plus or minus sign in the text box.
            return false;
        }

        // Only allow a minus or plus sign at the first character position.
        if (
            (
                (theCharacter == '-')
                || (theCharacter == '+')
            )
            && theTextBox.SelectionStart != 0
            )
        {
            // Then the user is trying to enter a minus or plus sign at some position 
            // OTHER than the first character position in the text box.
            return false;
        }

        // Only allow digits and decimal point AFTER any existing plus or minus sign
        if  (
                (
                    // Is digit or decimal point
                    char.IsDigit(theCharacter)
                    ||
                    (theCharacter == '.')
                )
                &&
                (
                    // A plus or minus sign EXISTS
                    (theTextBox.Text.IndexOf('-') > -1)
                    ||
                    (theTextBox.Text.IndexOf('+') > -1)
                )
                &&
                    // Attempting to put the character at the beginning of the field.
                    theTextBox.SelectionStart == 0
            )
        {
            // Then the user is trying to enter a digit or decimal point in front of a minus or plus sign.
            return false;
        }

        // Otherwise the character is perfectly fine for a decimal value and the character
        // may indeed be placed at the current insertion position.
        return true;
    }
8
8.08.2012 20:06:38

3 решение

1)

//Add to the textbox's KeyPress event
//using Regex for number only textBox

private void txtBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (!System.Text.RegularExpressions.Regex.IsMatch(e.KeyChar.ToString(), "\\d+"))
e.Handled = true;
}

2) другое решение от msdn

// Boolean flag used to determine when a character other than a number is entered.
private bool nonNumberEntered = false;
// Handle the KeyDown event to determine the type of character entered into the     control.
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
// Initialize the flag to false.
nonNumberEntered = false;
// Determine whether the keystroke is a number from the top of the keyboard.
if (e.KeyCode < Keys.D0 || e.KeyCode > Keys.D9)
{
    // Determine whether the keystroke is a number from the keypad.
    if (e.KeyCode < Keys.NumPad0 || e.KeyCode > Keys.NumPad9)
    {
        // Determine whether the keystroke is a backspace.
        if (e.KeyCode != Keys.Back)
        {
            // A non-numerical keystroke was pressed.
            // Set the flag to true and evaluate in KeyPress event.
            nonNumberEntered = true;
        }
    }
}

}

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    if (nonNumberEntered == true)
    {
       MessageBox.Show("Please enter number only..."); 
       e.Handled = true;
    }
}

источник http://msdn.microsoft.com/en-us/library/system.windows.forms.control.keypress(v=VS.90).aspx

3) с помощью MaskedTextBox: http://msdn.microsoft.com/en-us/library/system.windows.forms.maskedtextbox.aspx

0
9.08.2012 02:14:53

Вот простой автономный пользовательский элемент управления Winforms, полученный из стандартного TextBox, который допускает только ввод System.Int32 (его можно легко адаптировать для других типов, таких как System.Int64 и т. Д.). Он поддерживает операции копирования / вставки и отрицательные числа:

public class Int32TextBox : TextBox
{
    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        base.OnKeyPress(e);

        NumberFormatInfo fi = CultureInfo.CurrentCulture.NumberFormat;

        string c = e.KeyChar.ToString();
        if (char.IsDigit(c, 0))
            return;

        if ((SelectionStart == 0) && (c.Equals(fi.NegativeSign)))
            return;

        // copy/paste
        if ((((int)e.KeyChar == 22) || ((int)e.KeyChar == 3))
            && ((ModifierKeys & Keys.Control) == Keys.Control))
            return;

        if (e.KeyChar == '\b')
            return;

        e.Handled = true;
    }

    protected override void WndProc(ref System.Windows.Forms.Message m)
    {
        const int WM_PASTE = 0x0302;
        if (m.Msg == WM_PASTE)
        {
            string text = Clipboard.GetText();
            if (string.IsNullOrEmpty(text))
                return;

            if ((text.IndexOf('+') >= 0) && (SelectionStart != 0))
                return;

            int i;
            if (!int.TryParse(text, out i)) // change this for other integer types
                return;

            if ((i < 0) && (SelectionStart != 0))
                return;
        }
        base.WndProc(ref m);
    }

Обновление 2017 : мой первый ответ имеет некоторые проблемы:

  • вы можете ввести что-то длиннее целого числа данного типа (например, 2147483648 больше, чем Int32.MaxValue);
  • в целом, нет реальной проверки результата того, что было напечатано;
  • он обрабатывает только int32, вам нужно написать определенный производный элемент управления TextBox для каждого типа (Int64 и т. д.)

Поэтому я предложил другую, более общую версию, которая по-прежнему поддерживает копирование / вставку, знак + и - и т. Д.

public class ValidatingTextBox : TextBox
{
    private string _validText;
    private int _selectionStart;
    private int _selectionEnd;
    private bool _dontProcessMessages;

    public event EventHandler<TextValidatingEventArgs> TextValidating;

    protected virtual void OnTextValidating(object sender, TextValidatingEventArgs e) => TextValidating?.Invoke(sender, e);

    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        if (_dontProcessMessages)
            return;

        const int WM_KEYDOWN = 0x100;
        const int WM_ENTERIDLE = 0x121;
        const int VK_DELETE = 0x2e;

        bool delete = m.Msg == WM_KEYDOWN && (int)m.WParam == VK_DELETE;
        if ((m.Msg == WM_KEYDOWN && !delete) || m.Msg == WM_ENTERIDLE)
        {
            DontProcessMessage(() =>
            {
                _validText = Text;
                _selectionStart = SelectionStart;
                _selectionEnd = SelectionLength;
            });
        }

        const int WM_CHAR = 0x102;
        const int WM_PASTE = 0x302;
        if (m.Msg == WM_CHAR || m.Msg == WM_PASTE || delete)
        {
            string newText = null;
            DontProcessMessage(() =>
            {
                newText = Text;
            });

            var e = new TextValidatingEventArgs(newText);
            OnTextValidating(this, e);
            if (e.Cancel)
            {
                DontProcessMessage(() =>
                {
                    Text = _validText;
                    SelectionStart = _selectionStart;
                    SelectionLength = _selectionEnd;
                });
            }
        }
    }

    private void DontProcessMessage(Action action)
    {
        _dontProcessMessages = true;
        try
        {
            action();
        }
        finally
        {
            _dontProcessMessages = false;
        }
    }
}

public class TextValidatingEventArgs : CancelEventArgs
{
    public TextValidatingEventArgs(string newText) => NewText = newText;
    public string NewText { get; }
}

Для Int32 вы можете либо получить его, например:

public class Int32TextBox : ValidatingTextBox
{
    protected override void OnTextValidating(object sender, TextValidatingEventArgs e)
    {
        e.Cancel = !int.TryParse(e.NewText, out int i);
    }
}

или без деривации используйте новое событие TextValidating, например:

var vtb = new ValidatingTextBox();
...
vtb.TextValidating += (sender, e) => e.Cancel = !int.TryParse(e.NewText, out int i);

но хорошо то, что он работает с любой строкой и любой процедурой проверки.

36
18.10.2018 16:20:11
Это здорово, красиво и просто, легко используется и имеет дело с необычными попытками ввода. Спасибо!
WiredEarp 28.09.2015 05:14:11
Обратите внимание на версию 2017 года, когда есть одно значение, например, 1, и вы
Karen Payne 2.12.2017 14:04:13
Ваш ValidatingTextbox, безусловно, одна из лучших реализаций, которые я когда-либо видел. Просто и эффективно. Спасибо!
Samuel 11.09.2019 20:28:13

Я бы обработал это в событии KeyDown.

void TextBox_KeyDown(object sender, KeyEventArgs e)
        {
            char c = Convert.ToChar(e.PlatformKeyCode);
            if (!char.IsDigit(c))
            {
                e.Handled = true;
            }
        }
2
16.09.2012 23:57:22
А как насчет таких клавиш, как «Backspace», «Delete», «Arrow-Key-Left», «Arrow-Key-Right», Copy и Paste, цифр, введенных Numpad (они
user799821 27.05.2013 10:19:38
Просто добавьте еще несколько таких тестов: if (! Char.IsDigit (c) && c! = (Char) Keys.Back)
dnennis 29.12.2015 10:59:55

Это именно то, для чего были разработаны события Validated / Validating.

Вот статья MSDN по этой теме: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.validating.aspx

Версия TL; DR: проверьте свойство .Text в событии Validating и установите, e.Cancel=Trueкогда данные недействительны.

Когда вы устанавливаете e.Cancel = True, пользователь не может покинуть поле, но вам нужно будет дать ему некоторую обратную связь, что что-то не так. Я изменил цвет фона окна на светло-красный, чтобы указать на проблему. Обязательно установите его обратно, SystemColors.Windowкогда Validating вызывается с хорошим значением.

19
27.07.2013 00:40:10
+1 за упоминание очень API-идиоматического подхода. Я относительно новичок в Windows Forms, и это довольно джунгли функциональности и документов MSDN, так что также спасибо за конкретный указатель на документ Validating. <nitpick>ОП упоминает, что немедленное запрещение / указание недействительного символа является идеальным, но, Validatingпохоже, требует, чтобы фокус был перемещен в другую форму / элемент управления, прежде чем он вступит в силу. </nitpick>Тем не менее, это отличный подход, который всегда стоит рассмотреть в более общем случае.
William 23.07.2014 15:37:32

При нажатии кнопки вы можете проверить текстовое поле для цикла:

char[] c = txtGetCustomerId.Text.ToCharArray();
bool IsDigi = true;

for (int i = 0; i < c.Length; i++)
     {
       if (c[i] < '0' || c[i] > '9')
      { IsDigi = false; }
     }
 if (IsDigi)
    { 
     // do something
    }
0
25.08.2013 11:49:10

Этот работает с копированием и вставкой, перетаскиванием, клавишей вниз, предотвращает переполнение и довольно прост

public partial class IntegerBox : TextBox 
{
    public IntegerBox()
    {
        InitializeComponent();
        this.Text = 0.ToString();
    }

    protected override void OnPaint(PaintEventArgs pe)
    {
        base.OnPaint(pe);
    }

    private String originalValue = 0.ToString();

    private void Integerbox_KeyPress(object sender, KeyPressEventArgs e)
    {
        originalValue = this.Text;
    }

    private void Integerbox_TextChanged(object sender, EventArgs e)
    {
        try
        {
            if(String.IsNullOrWhiteSpace(this.Text))
            {
                this.Text = 0.ToString();
            }
            this.Text = Convert.ToInt64(this.Text.Trim()).ToString();
        }
        catch (System.OverflowException)
        {
            MessageBox.Show("Value entered is to large max value: " + Int64.MaxValue.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            this.Text = originalValue;
        }
        catch (System.FormatException)
        {                
            this.Text = originalValue;
        }
        catch (System.Exception ex)
        {
            this.Text = originalValue;
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK , MessageBoxIcon.Error);
        }
    }       
}
1
17.09.2013 13:50:04

Более простой ответ:

_textBox.TextChanged += delegate(System.Object o, System.EventArgs e)
{
    TextBox _tbox = o as TextBox;
    _tbox.Text = new string(_tbox.Text.Where(c => (char.IsDigit(c)) || (c == '.')).ToArray());
};
0
24.09.2013 21:01:58
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;
        }
    }
}

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

2
18.10.2013 12:50:02

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

вот демо

    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
5.01.2014 14:12:05
Спасибо, это очень полезно.
Kiran RS 18.09.2015 06:56:04

FAIL-SAFE и простой «рекурсивный» метод, который можно использовать с несколькими текстовыми полями.

Он блокирует неправильно введенные символы клавиатуры, а также вставленные значения и т. Д. Он принимает только целые числа, а максимальная длина номера - это максимальная длина строкового типа (то есть int, очень длинная!)

public void Check_If_Int_On_TextChanged(object sender, EventArgs e)
{
   // This method checks that each inputed character is a number. Any non-numeric
   // characters are removed from the text

   TextBox textbox = (TextBox)sender;

   // If the text is empty, return
   if (textbox.Text.Length == 0) { return; }

   // Check the new Text value if it's only numbers
   byte parsedValue;
   if (!byte.TryParse(textbox.Text[(textbox.Text.Length - 1)].ToString(), out parsedValue))
   {
      // Remove the last character as it wasn't a number
      textbox.Text = textbox.Text.Remove((textbox.Text.Length - 1));

      // Move the cursor to the end of text
      textbox.SelectionStart = textbox.Text.Length;
    }
 }
0
9.04.2014 13:58:45

Кажется, что многие из текущих ответов на этот вопрос вручную анализируют входной текст. Если вы ищете определенный встроенный числовой тип (например, 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
23.07.2014 22:59:26

просто используйте этот код в текстовом поле:

private void textBox1_TextChanged(object sender, EventArgs e)
{

    double parsedValue;

    if (!double.TryParse(textBox1.Text, out parsedValue))
    {
        textBox1.Text = "";
    }
}
4
13.03.2015 21:24:16

Я работал над набором компонентов, чтобы завершить недостающий материал в WinForms, вот он: Advanced Forms

В частности, это класс для Regex TextBox

/// <summary>Represents a Windows text box control that only allows input that matches a regular expression.</summary>
public class RegexTextBox : TextBox
{
    [NonSerialized]
    string lastText;

    /// <summary>A regular expression governing the input allowed in this text field.</summary>
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public virtual Regex Regex { get; set; }

    /// <summary>A regular expression governing the input allowed in this text field.</summary>
    [DefaultValue(null)]
    [Category("Behavior")]
    [Description("Sets the regular expression governing the input allowed for this control.")]
    public virtual string RegexString {
        get {
            return Regex == null ? string.Empty : Regex.ToString();
        }
        set {
            if (string.IsNullOrEmpty(value))
                Regex = null;
            else
                Regex = new Regex(value);
        }
    }

    protected override void OnTextChanged(EventArgs e) {
        if (Regex != null && !Regex.IsMatch(Text)) {
            int pos = SelectionStart - Text.Length + (lastText ?? string.Empty).Length;
            Text = lastText;
            SelectionStart = Math.Max(0, pos);
        }

        lastText = Text;

        base.OnTextChanged(e);
    }
}

Простого добавления чего-то вроде myNumbericTextBox.RegexString = "^(\\d+|)$";должно быть достаточно.

6
25.02.2015 08:23:39

мне нравится краткий код

    private void xmm_textbox_KeyPress(object sender, KeyPressEventArgs e) {
        double x;
        e.Handled = !double.TryParse(((TextBox)sender).Text, out x);
    }
0
4.07.2015 17:42:52

Я также искал лучший способ проверить только цифры в текстовом поле, и проблема с нажатием клавиш состояла в том, что он не поддерживает копирование вставкой по щелчку правой кнопкой мыши или в буфере обмена, поэтому придумал этот код, который проверяет, когда курсор покидает текстовое поле, а также проверяет наличие пустое поле (адаптированная версия newguy)

private void txtFirstValue_MouseLeave(object sender, EventArgs e)
{
    int num;
    bool isNum = int.TryParse(txtFirstValue.Text.Trim(), out num);

    if (!isNum && txtFirstValue.Text != String.Empty)
    {
        MessageBox.Show("The First Value You Entered Is Not a Number, Please Try Again", "Invalid Value Detected", MessageBoxButtons.OK, MessageBoxIcon.Error);
        txtFirstValue.Clear();
    }
}
1
6.02.2018 11:55:46
MouseLeave кажется действительно плохим выбором для использования события.
LarsTech 8.10.2015 20:20:15
@LarsTech, что я думал, что текстовое сообщение даже может вызвать сообщение об ошибке раньше, даже если пользователь понимает ошибку и пытается исправить ее, поэтому я думал, что я буду работать лучше. Как вы думаете, что является лучшим событием для этого случая?
Alston Antony 8.10.2015 21:00:24
@AlstonAntony поздний комментарий, я знаю. Но достаточно простого события щелчка, которое активируется при нажатии правой кнопки мыши, не так ли?
Takarii 3.05.2016 07:41:08

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

<asp:TextBox runat="server" ID="txtFrom"
     onkeypress="if(isNaN(String.fromCharCode(event.keyCode))) return false;">
4
10.05.2016 21:43:20

Не забывайте, что пользователь может вставить неверный текст в TextBox.

Если вы хотите ограничить это, следуйте приведенному ниже коду:

private void ultraTextEditor1_TextChanged(object sender, EventArgs e)
{
    string append="";
    foreach (char c in ultraTextEditor1.Text)
    {
        if ((!Char.IsNumber(c)) && (c != Convert.ToChar(Keys.Back)))
        {

        }
        else
        {
            append += c;
        }
    }

    ultraTextEditor1.Text = append;
}   
1
6.02.2018 11:53:19
Here is a simple solution that works for me.

public static bool numResult;
    public static bool checkTextisNumber(string numberVal)
    {
        try
        {
            if (numberVal.Equals("."))
            {
                numResult = true;
            }
            else if (numberVal.Equals(""))
            {
                numResult = true;
            }
            else
            {
                decimal number3 = 0;
                bool canConvert = decimal.TryParse(numberVal, out number3);
                if (canConvert == true)
                {
                    numResult = true;
                }
                else
                    numResult = false;
            }

        }
        catch (System.Exception ex)
        {
            numResult = false;
        }
        return numResult;
    }
    string correctNum;
    private void tBox_NumTester_TextChanged(object sender, TextChangedEventArgs e)
    {


        if(checkTextisNumber(tBox_NumTester.Text))
        {
            correctNum = tBox_NumTester.Text;
        }
        else
        {
            tBox_NumTester.Text = correctNum;
        }

    }
0
28.07.2016 03:31:09

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

numericUpDown1.Controls[0].Visible = false;

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

Маркировка:

YourNumericUpDown.Controls[0].visible = false 

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

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

4
6.02.2018 11:21:41
Принятый ответ не содержал никакой информации о том, как убрать кнопки «вверх-вниз», как это сделать неочевидно, поскольку нет никаких удобочитаемых интерфейсов для их включения или отключения. NumericUpDown на самом деле представляет собой набор элементов управления, содержащий текстовое поле и «спин-бокс» (кнопки вверх-вниз) и некоторую проверку кода для обработки ввода.
user2163234 27.11.2017 23:19:37