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

492

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

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

  • 10
    цифры или цифры? большая разница: даже целые числа могут стать отрицательными
  • 6
    Вопрос был предназначен для чисел, включая весь набор рациональных чисел.
Теги:
winforms
textbox

33 ответа

641
Лучший ответ

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

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

  • Обработайте соответствующие события клавиатуры, чтобы предотвратить что-либо, кроме числового ввода. У меня был успех с этими двумя обработчиками событий на стандартном 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

  • 2
    Я забыл, что числовое управление вверх-вниз существует. Это на самом деле то, что я должен использовать здесь вместо текстового поля. В будущем, когда у меня будет более сложная проверка, я буду использовать обработанное свойство с событием KeyPress.
  • 4
    Единственный недостаток NumericUpDown заключается в том, что он не обеспечивает обратной связи при вводе значения за пределами Максимального или Минимально допустимого значения - он просто меняет то, что вы ввели. TextBox может по крайней мере разрешить недопустимые значения, чтобы вы могли предупредить пользователя при отправке формы.
Показать ещё 14 комментариев
117

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

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

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

  • 0
    это не общее решение, так как оно работает только для интергеров. Я должен был реализовать такую вещь недавно, и я закончил с попыткой парсинга результирующей строки в число и разрешил ввод только в случае успешного разбора
  • 0
    Это может не работать, когда несколько методов обрабатывают события KeyPress из одного и того же текстового поля. Одно событие может установить для e.Handled значение true, а затем для другого может быть установлено значение false. В общем, лучше использовать if (...) e.Handled = true;
Показать ещё 4 комментария
38

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

    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);
        }
    }
  • 16
    Разве это не даст очень странный эффект, если вы наберете в середине числа?
  • 5
    а также должно быть: textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 1);
Показать ещё 5 комментариев
28

Вот простой автономный пользовательский элемент 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 и т.д.).

Итак, я придумал другую версию, более общую, которая все еще поддерживает copy/paste, + и - sign и т.д.

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);

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

  • 0
    Это здорово, красиво и просто, легко используется и связано с необычными попытками ввода. Спасибо!
  • 0
    Обратите внимание на версию 2017 года, когда есть одно значение, например, 1, и вы нажимаете клавишу Backspace, оно игнорируется, в то время как, если вы произнесете 120 и нажмете клавишу Backspace три раза, у нас останется 1.
17

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

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

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

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

  • 1
    +1 за упоминание очень API-идиоматического подхода. Я относительно новичок в Windows Forms, и это довольно джунгли функциональности и документов MSDN, так что также спасибо за конкретный указатель на документ для Validating . <nitpick> В OP упоминается, что немедленное запрещение / указание недействительного символа является идеальным, но для Validating видимому, требуется перенести фокус на другую форму / элемент управления, прежде чем он вступит в силу. </nitpick> Тем не менее, это отличный подход, который всегда стоит рассмотреть в более общем случае.
12

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

  • 1
    Я специально не хочу использовать MaskedTextBox. Форматы, которые они допускают, могут быть очень ограничивающими. Они работают для этого случая, но я хотел бы сделать что-то более общее.
11

Вы можете использовать событие 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();
    }
}
  • 0
    Похоже, это должно работать хорошо, если вы использовали Undo() , но это приводит к StackOverflowException .
  • 0
    Похоже, что свойство TextChanged является частью процедуры, которую вы хотите отменить (). У меня есть переменная для всего окна, и я использую public int txtBoxValue , и если tryParse не работает, я возвращаю текст в txtBox с помощью txtBox.Text = txtBoxValue.ToString();
5

Я работаю над набором компонентов для заполнения отсутствующих вещей в WinForms, вот он: Дополнительные формы

В частности, это класс для регулярного выражения 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+|)$"; должно быть достаточно.

4

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

private void textBox1_TextChanged(object sender, EventArgs e)
{

    double parsedValue;

    if (!double.TryParse(textBox1.Text, out parsedValue))
    {
        textBox1.Text = "";
    }
}
4

Это может быть полезно. Он позволяет "реальные" числовые значения, включая правильные десятичные точки и предшествующие знаки "плюс" или "минус". Вызовите его из соответствующего события 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;
    }
4

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

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

3

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

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

Похоже, что многие из текущих ответов на этот вопрос вручную анализируют входной текст. Если вы ищете определенный встроенный числовой тип (например, 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;
        }
    }
}

И, наконец, если вам нужно что-то полностью общее и не заботится о поддержке дизайнера:

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

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

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

    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;
    }
  • 0
    Спасибо, это очень полезно.
2
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

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

2

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

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

1

Оба числа и поплавки должны быть приняты, включая отрицательные числа.

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));
}
1

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

numericUpDown1.Controls[0].Visible = false;

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

Маркировка:

YourNumericUpDown.Controls[0].visible = false 

будет скрывать кнопки при сохранении основного кода.

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

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

Не забывайте, что пользователь может вставить недопустимый текст в 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

Я также искал лучший способ проверить только числа в текстовом поле и проблему с нажатием клавиши, если бы он не поддерживал скопировать вставку при щелчке правой кнопкой мыши или в буфер обмена, поэтому придумал этот код, который проверяет, когда курсор покидает текстовое поле, а также он проверяет пустое поле. (адаптированная версия 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();
    }
}
  • 0
    MouseLeave кажется действительно плохим выбором для использования события.
  • 0
    @LarsTech, что я думал, что текстовое сообщение даже может вызвать сообщение об ошибке раньше, даже если пользователь осознает ошибку и пытается исправить ее, поэтому я думал, что я буду работать лучше. Как вы думаете, это лучшее событие для этого случая?
Показать ещё 1 комментарий
1

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

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

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

void TextBox_KeyDown(object sender, KeyEventArgs e)
        {
            char c = Convert.ToChar(e.PlatformKeyCode);
            if (!char.IsDigit(c))
            {
                e.Handled = true;
            }
        }
  • 2
    А как насчет таких клавиш, как «Backspace», «Delete», «Arrow-Key-Left», «Arrow-Key-Right», «Копировать и вставить», цифры, введенные Numpad (они торгуются как! Цифра)
  • 0
    Просто добавьте еще несколько таких тестов: if (! Char.IsDigit (c) && c! = (Char) Keys.Back)
1

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

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

В основном вы можете нажать только 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;
    }
  • 2
    Это решение изобретает колесо с предостережениями. Локализация например.
0

Это мой подход:

  • с помощью linq (легко модифицировать фильтр)
  • код для копирования/вставки
  • сохраняет позицию каретки, когда вы нажимаете запрещенный символ
  • принимает левые нули
  • и любые номера размеров

    private void numeroCuenta_TextChanged(object sender, EventArgs e)
    {
        string org = numeroCuenta.Text;
        string formated = string.Concat(org.Where(c => (c >= '0' && c <= '9')));
        if (formated != org)
        {
            int s = numeroCuenta.SelectionStart;
            if (s > 0 && formated.Length > s && org[s - 1] != formated[s - 1]) s--;
            numeroCuenta.Text = formated;
            numeroCuenta.SelectionStart = s;
        }
    }
    
0

Я создал класс Re-Usable Textbox Extension для всех видов проверок и думал о его совместном использовании.

Все, что вам нужно сделать, это поднять событие TextChange, а затем вызвать метод Validate. Это выглядит так:

private void tbxAmount_TextChanged(object sender, EventArgs e)
{ 
    tbxAmount.Validate(TextValidator.ValidationType.Amount);
}

Вот класс расширения:

public static class TextValidator
{
    public enum ValidationType
    {
        Amount,
        Integer
    }

    /// <summary>
    /// Validate a textbox on text change.
    /// </summary>
    /// <param name="tbx"></param>
    /// <param name="validationType"></param>
    public static void Validate(this TextBox tbx, ValidationType validationType)
    {
        PerformValidation(tbx, validationType);
        tbx.Select(tbx.Text.Length, 0);
    }


    private static void PerformValidation(this TextBox tbx, ValidationType validationType)
    {
        char[] enteredString = tbx.Text.ToCharArray();
        switch (validationType)
        {
            case ValidationType.Amount:
                tbx.Text = AmountValidation(enteredString);
                break;

            case ValidationType.Integer:
                tbx.Text = IntegerValidation(enteredString);
                break;

            default:
                break;
        }

        tbx.SelectionStart = tbx.Text.Length;
    }



    private static string AmountValidation(char[] enteredString)
    {
        string actualString = string.Empty;
        int count = 0;
        foreach (char c in enteredString.AsEnumerable())
        {
            if (count >= 1 && c == '.')
            { actualString.Replace(c, ' '); actualString.Trim(); }
            else
            {
                if (Char.IsDigit(c))
                {
                    actualString = actualString + c;
                }

                if (c == '.')
                {
                    actualString = actualString + c; count++;
                }

                else
                {
                    actualString.Replace(c, ' ');
                    actualString.Trim();
                }
            }
        }
        return actualString;
    }


    private static string IntegerValidation(char[] enteredString)
    {
        string actualString = string.Empty;
        foreach (char c in enteredString.AsEnumerable())
        {
            if (Char.IsDigit(c))
            {
                actualString = actualString + c;
            }
            else
            {
                actualString.Replace(c, ' ');
                actualString.Trim();
            }
        }
        return actualString;
    }
}

Здесь вы можете найти полный код

0
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

Мне нравится сложный код

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

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 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

Упрощенный ответ:

_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

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

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

3 решение

1)

//Add to the textbox 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
int Number;
bool isNumber;
isNumber = int32.TryPase(textbox1.text, out Number);

if (!isNumber)
{ 
    (code if not an integer);
}
else
{
    (code if an integer);
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню