Запись числовых данных в WPF

Как будто вы пытаетесь получить доступ к объекту, который является null. Рассмотрим ниже пример:

TypeA objA;

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

См. Также этот пример:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
64
задан Arcturus 11 January 2019 в 10:08
поделиться

12 ответов

Как насчет:

protected override void OnPreviewTextInput(System.Windows.Input.TextCompositionEventArgs e)
{
    e.Handled = !AreAllValidNumericChars(e.Text);
    base.OnPreviewTextInput(e);
}

private bool AreAllValidNumericChars(string str)
{
    foreach(char c in str)
    {
        if(!Char.IsNumber(c)) return false;
    }

    return true;
}
56
ответ дан Markus Safar 24 November 2019 в 15:55
поделиться

Вы не можете только использовать что-то как следующее?

int numericValue = 0;

if (false == int.TryParse(yourInput, out numericValue))
{
    // handle non-numeric input
}
0
ответ дан Markus Safar 24 November 2019 в 15:55
поделиться
private void txtNumericValue_PreviewKeyDown(object sender, KeyEventArgs e)
{
    KeyConverter converter = new KeyConverter();

    string key = converter.ConvertToString(e.Key);

    if (key != null && key.Length == 1)
    {
        e.Handled = Char.IsDigit(key[0]) == false;
    }
}

Это - самая легкая техника, которую я нашел для выполнения этого. Вниз сторона - то, что контекстное меню TextBox все еще позволяет нечисленные данные через Вставку. Для разрешения этого быстро, я просто добавил атрибут/свойство: ContextMenu = "{x:Null}" к TextBox, таким образом, запрещающему его. Не идеальный, но для моего сценария это будет достаточно.

, Очевидно, Вы могли добавить еще несколько ключей/символов в тесте для включения дополнительных допустимых значений (например,'.', '$' и т.д....)

0
ответ дан 24 November 2019 в 15:55
поделиться

Назовите меня сумасшедшим, но почему бы не поместить плюс, и минус кнопки в любой стороне TextBox управляют и просто препятствуют тому, чтобы TextBox получил фокус курсора, таким образом, создав Ваше собственное дешевое управление NumericUpDown?

0
ответ дан tags2k 24 November 2019 в 15:55
поделиться

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

<TextBox local:TextBoxNumbers.SingleDelta="1">100</TextBox>

, Это на самом деле не решает проблемы проверки, которые упомянуты в этом вопросе, но это обращается к тому, что я делаю о не наличии числового,/вниз управляют. Используя его для немного, я думаю, что мне мог бы на самом деле понравиться он лучше, чем старые числовые/вниз управляют.

код не прекрасен, но он обрабатывает случаи, которые мне был нужен он для обработки:

  • Up стрелка, Down стрелка
  • Shift + Up стрелка, Shift + Down стрелка
  • Page Up, Page Down
  • Привязка Converter на текстовом свойстве

Code behind

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;

namespace Helpers
{
    public class TextBoxNumbers
    {    
        public static Decimal GetSingleDelta(DependencyObject obj)
        {
            return (Decimal)obj.GetValue(SingleDeltaProperty);
        }

        public static void SetSingleDelta(DependencyObject obj, Decimal value)
        {
            obj.SetValue(SingleDeltaProperty, value);
        }

        // Using a DependencyProperty as the backing store for SingleValue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SingleDeltaProperty =
            DependencyProperty.RegisterAttached("SingleDelta", typeof(Decimal), typeof(TextBoxNumbers), new UIPropertyMetadata(0.0m, new PropertyChangedCallback(f)));

        public static void f(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            TextBox t = o as TextBox;

            if (t == null)
                return;

            t.PreviewKeyDown += new System.Windows.Input.KeyEventHandler(t_PreviewKeyDown);
        }

        private static Decimal GetSingleValue(DependencyObject obj)
        {
            return GetSingleDelta(obj);
        }

        private static Decimal GetDoubleValue(DependencyObject obj)
        {
            return GetSingleValue(obj) * 10;
        }

        private static Decimal GetTripleValue(DependencyObject obj)
        {
            return GetSingleValue(obj) * 100;
        }

        static void t_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            TextBox t = sender as TextBox;
            Decimal i;

            if (t == null)
                return;

            if (!Decimal.TryParse(t.Text, out i))
                return;

            switch (e.Key)
            {
                case System.Windows.Input.Key.Up:
                    if (Keyboard.Modifiers == ModifierKeys.Shift)
                        i += GetDoubleValue(t);
                    else
                        i += GetSingleValue(t);
                    break;

                case System.Windows.Input.Key.Down:
                    if (Keyboard.Modifiers == ModifierKeys.Shift)
                        i -= GetDoubleValue(t);
                    else
                        i -= GetSingleValue(t);
                    break;

                case System.Windows.Input.Key.PageUp:
                    i += GetTripleValue(t);
                    break;

                case System.Windows.Input.Key.PageDown:
                    i -= GetTripleValue(t);
                    break;

                default:
                    return;
            }

            if (BindingOperations.IsDataBound(t, TextBox.TextProperty))
            {
                try
                {
                    Binding binding = BindingOperations.GetBinding(t, TextBox.TextProperty);
                    t.Text = (string)binding.Converter.Convert(i, null, binding.ConverterParameter, binding.ConverterCulture);
                }
                catch
                {
                    t.Text = i.ToString();
                }
            }
            else
                t.Text = i.ToString();
        }
    }
}
10
ответ дан Markus Safar 24 November 2019 в 15:55
поделиться

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

Иначе, Вы могли всегда отключать Вставку также!

1
ответ дан Nidonocu 24 November 2019 в 15:55
поделиться

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

Regex NumEx = new Regex(@"^-?\d*\.?\d*$");

private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
    if (sender is TextBox)
    {
        string text = (sender as TextBox).Text + e.Text;
        e.Handled = !NumEx.IsMatch(text);
    }
    else
        throw new NotImplementedException("TextBox_PreviewTextInput Can only Handle TextBoxes");
}

Теперь есть гораздо лучший способ сделать это в WPF и Silverlight. Если ваш элемент управления привязан к свойству, все, что вам нужно сделать, это немного изменить оператор привязки. Используйте для привязки следующее:

<TextBox Text="{Binding Number, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}"/>

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

13
ответ дан 24 November 2019 в 15:55
поделиться
Private Sub Value1TextBox_PreviewTextInput(ByVal sender As Object, ByVal e As TextCompositionEventArgs) Handles Value1TextBox.PreviewTextInput
    Try
        If Not IsNumeric(e.Text) Then
            e.Handled = True
        End If
    Catch ex As Exception
    End Try
End Sub

работал для меня.

0
ответ дан 24 November 2019 в 15:55
поделиться
void PreviewTextInputHandler(object sender, TextCompositionEventArgs e)
{
    string sVal = e.Text;
    int val = 0;

    if (sVal != null && sVal.Length > 0)
    {
        if (int.TryParse(sVal, out val))
        {
            e.Handled = false;
        }
        else
        {
            e.Handled = true;
        }
    }
}
0
ответ дан 24 November 2019 в 15:55
поделиться
public class NumericTextBox : TextBox
{
    public NumericTextBox()
        : base()
    {
        DataObject.AddPastingHandler(this, new DataObjectPastingEventHandler(CheckPasteFormat));
    }

    private Boolean CheckFormat(string text)
    {
        short val;
        return Int16.TryParse(text, out val);
    }

    private void CheckPasteFormat(object sender, DataObjectPastingEventArgs e)
    {
        var isText = e.SourceDataObject.GetDataPresent(System.Windows.DataFormats.Text, true);

        if (isText)
        {
            var text = e.SourceDataObject.GetData(DataFormats.Text) as string;
            if (CheckFormat(text))
            {
                return;
            }
        }

        e.CancelCommand();
    }

    protected override void OnPreviewTextInput(System.Windows.Input.TextCompositionEventArgs e)
    {
        if (!CheckFormat(e.Text))
        {
            e.Handled = true;
        }
        else
        {
            base.OnPreviewTextInput(e);
        }
    }
}

Кроме того, вы можете настроить поведение парсинга, предоставив соответствующие свойства зависимости.

2
ответ дан 24 November 2019 в 15:55
поделиться

Добавьте это к основному решению, чтобы убедиться, что привязка обновляется до нуля, когда текстовое поле очищается.

protected override void OnPreviewKeyUp(System.Windows.Input.KeyEventArgs e)
{
    base.OnPreviewKeyUp(e);

    if (BindingOperations.IsDataBound(this, TextBox.TextProperty))
    {
        if (this.Text.Length == 0)
        {
            this.SetValue(TextBox.TextProperty, "0");
            this.SelectAll();
        }
    }
}
1
ответ дан 24 November 2019 в 15:55
поделиться

Я решил упростить ответ, отмеченный здесь как ответ, до 2 строк, используя выражение LINQ.

e.Handled = !e.Text.All(Char.IsNumber);
base.OnPreviewTextInput(e);
10
ответ дан 24 November 2019 в 15:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: