如何让TextBox只接受WPF中的数字输入?

Gif*_*guy 317 c# wpf xaml textbox numericupdown

我想接受数字和小数点,但没有迹象.

我已经使用Windows窗体的NumericUpDown控件和Microsoft的NumericUpDown自定义控件示例查看了示例.但到目前为止,似乎NumericUpDown(WPF支持或不支持)不会提供我想要的功能.我的应用程序的设计方式,没有人在他们正确的头脑中想要弄乱箭头.在我的申请中,它们没有任何实际意义.

所以我正在寻找一种简单的方法来使标准的WPF TextBox只接受我想要的字符.这可能吗?这是实用的吗?

Ray*_*Ray 393

添加预览文本输入事件.像这样:<TextBox PreviewTextInput="PreviewTextInput" />.

然后在里面设置e.Handledif是否允许文本.e.Handled = !IsTextAllowed(e.Text);

我在IsTextAllowed方法中使用一个简单的正则表达式来查看我是否应该允许他们输入的内容.在我的情况下,我只想允许数字,点和破折号.

private static readonly Regex _regex = new Regex("[^0-9.-]+"); //regex that matches disallowed text
private static bool IsTextAllowed(string text)
{
    return !_regex.IsMatch(text);
}
Run Code Online (Sandbox Code Playgroud)

如果你想防止不正确的数据粘贴挂钩的DataObject.Pasting事件DataObject.Pasting="TextBoxPasting"在这里(代码摘录):

// Use the DataObject.Pasting Handler 
private void TextBoxPasting(object sender, DataObjectPastingEventArgs e)
{
    if (e.DataObject.GetDataPresent(typeof(String)))
    {
        String text = (String)e.DataObject.GetData(typeof(String));
        if (!IsTextAllowed(text))
        {
            e.CancelCommand();
        }
    }
    else
    {
        e.CancelCommand();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 答案的重点不在于指定完美的正则表达式,它是为了展示如何使用WPF来过滤某人键入的内容. (142认同)
  • [Space]不会触发PreviewTextInput事件. (24认同)
  • 请注意,此答案仅检查您键入的内容,因此您可以输入3-.3 (14认同)
  • 你的正则表达式不允许科学记数法(1e5),如果这很重要的话. (5认同)
  • 像`double.TryParse()`这样的东西可能会使用相同数量的行来实现,并且更灵活. (4认同)
  • `e.Handled =!IsTextAllowed(e.Text);`与中文不兼容. (2认同)
  • @Mehrad:使用Double.TryParse并根据它是否成功进行过滤 (2认同)
  • @ThomasWeller double.TryParse 不接受点`.`,因为`e.Text` 只返回最后一个输入字符,而点不能解析为双精度。 (2认同)

Kis*_*hor 177

事件处理程序正在预览文本输入.这里正则表达式只有在不是数字的情况下才匹配文本输入,然后它不会进入文本框.

如果只想要字母,则将正则表达式替换为[^a-zA-Z].

XAML

<TextBox Name="NumberTextBox" PreviewTextInput="NumberValidationTextBox"/>
Run Code Online (Sandbox Code Playgroud)

XAML.CS文件

using System.Text.RegularExpressions;
private void NumberValidationTextBox(object sender, TextCompositionEventArgs e)
{
    Regex regex = new Regex("[^0-9]+");
    e.Handled = regex.IsMatch(e.Text);
}
Run Code Online (Sandbox Code Playgroud)

  • 请不要只发布代码.添加一些解释 (4认同)
  • 我喜欢这个比实际答案更简单,简单.实际答案需要两种方法来获得相同的结果. (3认同)
  • @Jagd 建议的答案是更好地分离关注点。但是,您也可以在此验证中设置任意多个文本框。只需添加 PreviewTextInput="NumberValidationTextBox"。(就像其他答案一样!) (2认同)
  • 要处理 +- 和小数点,请使用此正则表达式 http://stackoverflow.com/a/13686481/4146066 (2认同)

Wil*_*l P 80

我使用了一些已经存在的东西并使用行为对其进行了自己的改动,所以我不必在大量的视图中传播这段代码......

public class AllowableCharactersTextBoxBehavior : Behavior<TextBox>
{
    public static readonly DependencyProperty RegularExpressionProperty =
         DependencyProperty.Register("RegularExpression", typeof(string), typeof(AllowableCharactersTextBoxBehavior),
         new FrameworkPropertyMetadata(".*"));
    public string RegularExpression
    {
        get
        {
            return (string)base.GetValue(RegularExpressionProperty);
        }
        set
        {
            base.SetValue(RegularExpressionProperty, value);
        }
    }

    public static readonly DependencyProperty MaxLengthProperty =
        DependencyProperty.Register("MaxLength", typeof(int), typeof(AllowableCharactersTextBoxBehavior),
        new FrameworkPropertyMetadata(int.MinValue));
    public int MaxLength
    {
        get
        {
            return (int)base.GetValue(MaxLengthProperty);
        }
        set
        {
            base.SetValue(MaxLengthProperty, value);
        }
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.PreviewTextInput += OnPreviewTextInput;
        DataObject.AddPastingHandler(AssociatedObject, OnPaste);
    }

    private void OnPaste(object sender, DataObjectPastingEventArgs e)
    {
        if (e.DataObject.GetDataPresent(DataFormats.Text))
        {
            string text = Convert.ToString(e.DataObject.GetData(DataFormats.Text));

            if (!IsValid(text, true))
            {
                e.CancelCommand();
            }
        }
        else
        {
            e.CancelCommand();
        }
    }

    void OnPreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
    {
        e.Handled = !IsValid(e.Text, false);
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.PreviewTextInput -= OnPreviewTextInput;
        DataObject.RemovePastingHandler(AssociatedObject, OnPaste);
    }

    private bool IsValid(string newText, bool paste)
    {
        return !ExceedsMaxLength(newText, paste) && Regex.IsMatch(newText, RegularExpression);
    }

    private bool ExceedsMaxLength(string newText, bool paste)
    {
        if (MaxLength == 0) return false;

        return LengthOfModifiedText(newText, paste) > MaxLength;
    }

    private int LengthOfModifiedText(string newText, bool paste)
    {
        var countOfSelectedChars = this.AssociatedObject.SelectedText.Length;
        var caretIndex = this.AssociatedObject.CaretIndex;
        string text = this.AssociatedObject.Text;

        if (countOfSelectedChars > 0 || paste)
        {
            text = text.Remove(caretIndex, countOfSelectedChars);
            return text.Length + newText.Length;
        }
        else
        {
            var insert = Keyboard.IsKeyToggled(Key.Insert);

            return insert && caretIndex < text.Length ? text.Length : text.Length + newText.Length;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是相关的视图代码:

<TextBox MaxLength="50" TextWrapping="Wrap" MaxWidth="150" Margin="4"
 Text="{Binding Path=FileNameToPublish}" >
     <interactivity:Interaction.Behaviors>
         <v:AllowableCharactersTextBoxBehavior RegularExpression="^[0-9.\-]+$" MaxLength="50" />
     </interactivity:Interaction.Behaviors>
</TextBox>
Run Code Online (Sandbox Code Playgroud)

  • 你好.我知道这有点晚了但是我正在尝试实现这个但是我一直都会遇到错误.我猜我错过了一些参考文献.在创建类之后,是否有任何打算输入除默认值之外的内容? (2认同)

Ale*_*aus 57

这是WilP答案的改进解决方案.我的改进是:

  • 改进了DelBackspace按钮的行为
  • 添加EmptyValue属性,如果空字符串不合适
  • 修正了一些小错字
/// <summary>
///     Regular expression for Textbox with properties: 
///         <see cref="RegularExpression"/>, 
///         <see cref="MaxLength"/>,
///         <see cref="EmptyValue"/>.
/// </summary>
public class TextBoxInputRegExBehaviour : Behavior<TextBox>
{
    #region DependencyProperties
    public static readonly DependencyProperty RegularExpressionProperty =
        DependencyProperty.Register("RegularExpression", typeof(string), typeof(TextBoxInputRegExBehaviour), new FrameworkPropertyMetadata(".*"));

    public string RegularExpression
    {
        get { return (string)GetValue(RegularExpressionProperty); }
        set { SetValue(RegularExpressionProperty, value); }
    }

    public static readonly DependencyProperty MaxLengthProperty =
        DependencyProperty.Register("MaxLength", typeof(int), typeof(TextBoxInputRegExBehaviour),
                                        new FrameworkPropertyMetadata(int.MinValue));

    public int MaxLength
    {
        get { return (int)GetValue(MaxLengthProperty); }
        set { SetValue(MaxLengthProperty, value); }
    }

    public static readonly DependencyProperty EmptyValueProperty =
        DependencyProperty.Register("EmptyValue", typeof(string), typeof(TextBoxInputRegExBehaviour), null);

    public string EmptyValue
    {
        get { return (string)GetValue(EmptyValueProperty); }
        set { SetValue(EmptyValueProperty, value); }
    }
    #endregion

    /// <summary>
    ///     Attach our behaviour. Add event handlers
    /// </summary>
    protected override void OnAttached()
    {
        base.OnAttached();

        AssociatedObject.PreviewTextInput += PreviewTextInputHandler;
        AssociatedObject.PreviewKeyDown += PreviewKeyDownHandler;
        DataObject.AddPastingHandler(AssociatedObject, PastingHandler);
    }

    /// <summary>
    ///     Deattach our behaviour. remove event handlers
    /// </summary>
    protected override void OnDetaching()
    {
        base.OnDetaching();

        AssociatedObject.PreviewTextInput -= PreviewTextInputHandler;
        AssociatedObject.PreviewKeyDown -= PreviewKeyDownHandler;
        DataObject.RemovePastingHandler(AssociatedObject, PastingHandler);
    }

    #region Event handlers [PRIVATE] --------------------------------------

    void PreviewTextInputHandler(object sender, TextCompositionEventArgs e)
    {
        string text;
        if (this.AssociatedObject.Text.Length < this.AssociatedObject.CaretIndex)
            text = this.AssociatedObject.Text;
        else
        {
            //  Remaining text after removing selected text.
            string remainingTextAfterRemoveSelection;

            text = TreatSelectedText(out remainingTextAfterRemoveSelection)
                ? remainingTextAfterRemoveSelection.Insert(AssociatedObject.SelectionStart, e.Text)
                : AssociatedObject.Text.Insert(this.AssociatedObject.CaretIndex, e.Text);
        }

        e.Handled = !ValidateText(text);
    }

    /// <summary>
    ///     PreviewKeyDown event handler
    /// </summary>
    void PreviewKeyDownHandler(object sender, KeyEventArgs e)
    {
        if (string.IsNullOrEmpty(this.EmptyValue))
            return;

        string text = null;

        // Handle the Backspace key
        if (e.Key == Key.Back)
        {
            if (!this.TreatSelectedText(out text))
            {
                if (AssociatedObject.SelectionStart > 0)
                    text = this.AssociatedObject.Text.Remove(AssociatedObject.SelectionStart - 1, 1);
            }
        }
        // Handle the Delete key
        else if (e.Key == Key.Delete)
        {
            // If text was selected, delete it
            if (!this.TreatSelectedText(out text) && this.AssociatedObject.Text.Length > AssociatedObject.SelectionStart)
            {
                // Otherwise delete next symbol
                text = this.AssociatedObject.Text.Remove(AssociatedObject.SelectionStart, 1);
            }
        }

        if (text == string.Empty)
        {
            this.AssociatedObject.Text = this.EmptyValue;
            if (e.Key == Key.Back)
                AssociatedObject.SelectionStart++;
            e.Handled = true;
        }
    }

    private void PastingHandler(object sender, DataObjectPastingEventArgs e)
    {
        if (e.DataObject.GetDataPresent(DataFormats.Text))
        {
            string text = Convert.ToString(e.DataObject.GetData(DataFormats.Text));

            if (!ValidateText(text))
                e.CancelCommand();
        }
        else
            e.CancelCommand();
    }
    #endregion Event handlers [PRIVATE] -----------------------------------

    #region Auxiliary methods [PRIVATE] -----------------------------------

    /// <summary>
    ///     Validate certain text by our regular expression and text length conditions
    /// </summary>
    /// <param name="text"> Text for validation </param>
    /// <returns> True - valid, False - invalid </returns>
    private bool ValidateText(string text)
    {
        return (new Regex(this.RegularExpression, RegexOptions.IgnoreCase)).IsMatch(text) && (MaxLength == int.MinValue || text.Length <= MaxLength);
    }

    /// <summary>
    ///     Handle text selection
    /// </summary>
    /// <returns>true if the character was successfully removed; otherwise, false. </returns>
    private bool TreatSelectedText(out string text)
    {
        text = null;
        if (AssociatedObject.SelectionLength <= 0) 
            return false;

        var length = this.AssociatedObject.Text.Length;
        if (AssociatedObject.SelectionStart >= length)
            return true;

        if (AssociatedObject.SelectionStart + AssociatedObject.SelectionLength >= length)
            AssociatedObject.SelectionLength = length - AssociatedObject.SelectionStart;

        text = this.AssociatedObject.Text.Remove(AssociatedObject.SelectionStart, AssociatedObject.SelectionLength);
        return true;
    }
    #endregion Auxiliary methods [PRIVATE] --------------------------------
}
Run Code Online (Sandbox Code Playgroud)

用法非常简单:

<i:Interaction.Behaviors>
    <behaviours:TextBoxInputRegExBehaviour RegularExpression="^\d+$" MaxLength="9" EmptyValue="0" />
</i:Interaction.Behaviors>
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案相当好。但你犯了一个小错误:当不设置“MaxLength”时,测试新文本时,你的条件“(this.MaxLength == 0 || text.Length &lt;= this.MaxLength)”总是返回“false”。最好是 `(this.MaxLength == int.MinValue || text.Length &lt;= this.MaxLength)`,因为您将 `int.MinValue` 设置为 `MaxLength` 的默认值。 (2认同)

Snz*_*pta 29

这是使用MVVM执行此操作的一种非常简单易用的方法.

在视图模型中使用整数属性绑定textBox,这将像gem一样...它甚至会在文本框中输入非整数时显示验证.

XAML代码:

<TextBox x:Name="contactNoTxtBox"  Text="{Binding contactNo}" />
Run Code Online (Sandbox Code Playgroud)

查看型号代码:

private long _contactNo;
public long contactNo
{
    get { return _contactNo; }
    set
    {
        if (value == _contactNo)
            return;
        _contactNo = value;
        OnPropertyChanged();
    }
}
Run Code Online (Sandbox Code Playgroud)


Ste*_*ton 23

添加一个VALIDATION RULE,以便在文本更改时检查以确定数据是否为数字,如果是,则允许继续处理,如果不是,则提示用户该字段仅接受数字数据.

阅读Windows Presentation Foundation中的验证

  • 这不是SO标准的真正答案. (6认同)

Bri*_*nas 23

Extented WPF Toolkit有一个:NumericUpDown 在此输入图像描述

  • 请注意,`NumericUpDown`现在已经过时了.您可以使用更新的工具包中的`DecimalUpDown` [Extended WPF Toolkit™Community Edition](http://wpftoolkit.codeplex.com/wikipage?title=NumericUpDown&referringTitle=Home) (5认同)

gou*_*oul 18

也可以简单地实现验证规则并将其应用于TextBox:

  <TextBox>
    <TextBox.Text>
      <Binding Path="OnyDigitInput" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
        <Binding.ValidationRules>
          <conv:OnlyDigitsValidationRule />
        </Binding.ValidationRules>
      </Binding>
    </TextBox.Text>
Run Code Online (Sandbox Code Playgroud)

随着规则的实施如下(使用与其他答案中提出的相同的正则表达式):

public class OnlyDigitsValidationRule : ValidationRule
{
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        var validationResult = new ValidationResult(true, null);

        if(value != null)
        {
            if (!string.IsNullOrEmpty(value.ToString()))
            {
                var regex = new Regex("[^0-9.-]+"); //regex that matches disallowed text
                var parsingOk = !regex.IsMatch(value.ToString());
                if (!parsingOk)
                {
                    validationResult = new ValidationResult(false, "Illegal Characters, Please Enter Numeric Value");
                }
            }
        }

        return validationResult;
    }
}
Run Code Online (Sandbox Code Playgroud)


Ant*_*ony 14

在这里,我有一个灵感来自Ray的答案的简单解决方案.这应该足以识别任何形式的数字.

如果您只想要正数,整数值或精确到最大小数位数的值等,也可以轻松修改此解决方案.


正如Ray的回答所示,您需要先添加一个PreviewTextInput事件:

<TextBox PreviewTextInput="TextBox_OnPreviewTextInput"/>
Run Code Online (Sandbox Code Playgroud)

然后将以下代码放在后面的代码中:

private void TextBox_OnPreviewTextInput(object sender, TextCompositionEventArgs e)
{
    var textBox = sender as TextBox;
    // Use SelectionStart property to find the caret position.
    // Insert the previewed text into the existing text in the textbox.
    var fullText = textBox.Text.Insert(textBox.SelectionStart, e.Text);

    double val;
    // If parsing is successful, set Handled to false
    e.Handled = !double.TryParse(fullText, out val);
}
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这个答案很简单有效+ (4认同)
  • 仍然允许有人将字符串粘贴到文本框中 (2认同)

Ami*_*iri 10

另一种方法是使用附加行为,我实现了我的自定义TextBoxHelper类,该类可用于整个项目的文本框。因为我认为为此目的订阅每个文本框和每个单独的 XAML 文件中的事件可能非常耗时。

我实现的 TextBoxHelper 类具有以下功能:

  • 过滤和只接受DoubleIntUintNatural格式的数字
  • 过滤和只接受奇数号码
  • 处理粘贴事件处理程序以防止将无效文本粘贴到我们的数字文本框中
  • 可以设置一个默认值,通过订阅文本框 TextChanged 事件,该将用于防止无效数据作为最后一次拍摄

下面是 TextBoxHelper 类的实现:

public static class TextBoxHelper
{
    #region Enum Declarations

    public enum NumericFormat
    {
        Double,
        Int,
        Uint,
        Natural
    }

    public enum EvenOddConstraint
    {
        All,
        OnlyEven,
        OnlyOdd
    }

    #endregion

    #region Dependency Properties & CLR Wrappers

    public static readonly DependencyProperty OnlyNumericProperty =
        DependencyProperty.RegisterAttached("OnlyNumeric", typeof(NumericFormat?), typeof(TextBoxHelper),
            new PropertyMetadata(null, DependencyPropertiesChanged));
    public static void SetOnlyNumeric(TextBox element, NumericFormat value) =>
        element.SetValue(OnlyNumericProperty, value);
    public static NumericFormat GetOnlyNumeric(TextBox element) =>
        (NumericFormat) element.GetValue(OnlyNumericProperty);


    public static readonly DependencyProperty DefaultValueProperty =
        DependencyProperty.RegisterAttached("DefaultValue", typeof(string), typeof(TextBoxHelper),
            new PropertyMetadata(null, DependencyPropertiesChanged));
    public static void SetDefaultValue(TextBox element, string value) =>
        element.SetValue(DefaultValueProperty, value);
    public static string GetDefaultValue(TextBox element) => (string) element.GetValue(DefaultValueProperty);


    public static readonly DependencyProperty EvenOddConstraintProperty =
        DependencyProperty.RegisterAttached("EvenOddConstraint", typeof(EvenOddConstraint), typeof(TextBoxHelper),
            new PropertyMetadata(EvenOddConstraint.All, DependencyPropertiesChanged));
    public static void SetEvenOddConstraint(TextBox element, EvenOddConstraint value) =>
        element.SetValue(EvenOddConstraintProperty, value);
    public static EvenOddConstraint GetEvenOddConstraint(TextBox element) =>
        (EvenOddConstraint)element.GetValue(EvenOddConstraintProperty);

    #endregion

    #region Dependency Properties Methods

    private static void DependencyPropertiesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (!(d is TextBox textBox))
            throw new Exception("Attached property must be used with TextBox.");

        switch (e.Property.Name)
        {
            case "OnlyNumeric":
            {
                var castedValue = (NumericFormat?) e.NewValue;

                if (castedValue.HasValue)
                {
                    textBox.PreviewTextInput += TextBox_PreviewTextInput;
                    DataObject.AddPastingHandler(textBox, TextBox_PasteEventHandler);
                }
                else
                {
                    textBox.PreviewTextInput -= TextBox_PreviewTextInput;
                    DataObject.RemovePastingHandler(textBox, TextBox_PasteEventHandler);
                }

                break;
            }

            case "DefaultValue":
            {
                var castedValue = (string) e.NewValue;

                if (castedValue != null)
                {
                    textBox.TextChanged += TextBox_TextChanged;
                }
                else
                {
                    textBox.TextChanged -= TextBox_TextChanged;
                }

                break;
            }
        }
    }

    #endregion

    private static void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
    {
        var textBox = (TextBox)sender;

        string newText;

        if (textBox.SelectionLength == 0)
        {
            newText = textBox.Text.Insert(textBox.SelectionStart, e.Text);
        }
        else
        {
            var textAfterDelete = textBox.Text.Remove(textBox.SelectionStart, textBox.SelectionLength);

            newText = textAfterDelete.Insert(textBox.SelectionStart, e.Text);
        }

        var evenOddConstraint = GetEvenOddConstraint(textBox);

        switch (GetOnlyNumeric(textBox))
        {
            case NumericFormat.Double:
            {
                if (double.TryParse(newText, out double number))
                {
                    switch (evenOddConstraint)
                    {
                        case EvenOddConstraint.OnlyEven:

                            if (number % 2 != 0)
                                e.Handled = true;
                            else
                                e.Handled = false;

                            break;

                        case EvenOddConstraint.OnlyOdd:

                            if (number % 2 == 0)
                                e.Handled = true;
                            else
                                e.Handled = false;

                            break;
                    }
                }
                else
                    e.Handled = true;

                break;
            }

            case NumericFormat.Int:
            {
                if (int.TryParse(newText, out int number))
                {
                    switch (evenOddConstraint)
                    {
                        case EvenOddConstraint.OnlyEven:

                            if (number % 2 != 0)
                                e.Handled = true;
                            else
                                e.Handled = false;

                            break;

                        case EvenOddConstraint.OnlyOdd:

                            if (number % 2 == 0)
                                e.Handled = true;
                            else
                                e.Handled = false;

                            break;
                    }
                }
                else
                    e.Handled = true;

                break;
            }

            case NumericFormat.Uint:
            {
                if (uint.TryParse(newText, out uint number))
                {
                    switch (evenOddConstraint)
                    {
                        case EvenOddConstraint.OnlyEven:

                            if (number % 2 != 0)
                                e.Handled = true;
                            else
                                e.Handled = false;

                            break;

                        case EvenOddConstraint.OnlyOdd:

                            if (number % 2 == 0)
                                e.Handled = true;
                            else
                                e.Handled = false;

                            break;
                    }
                }
                else
                    e.Handled = true;

                break;
            }

            case NumericFormat.Natural:
            {
                if (uint.TryParse(newText, out uint number))
                {
                    if (number == 0)
                        e.Handled = true;
                    else
                    {
                        switch (evenOddConstraint)
                        {
                            case EvenOddConstraint.OnlyEven:

                                if (number % 2 != 0)
                                    e.Handled = true;
                                else
                                    e.Handled = false;

                                break;

                            case EvenOddConstraint.OnlyOdd:

                                if (number % 2 == 0)
                                    e.Handled = true;
                                else
                                    e.Handled = false;

                                break;
                        }
                    }
                }
                else
                    e.Handled = true;

                break;
            }
        }
    }

    private static void TextBox_PasteEventHandler(object sender, DataObjectPastingEventArgs e)
    {
        var textBox = (TextBox)sender;

        if (e.DataObject.GetDataPresent(typeof(string)))
        {
            var clipboardText = (string) e.DataObject.GetData(typeof(string));

            var newText = textBox.Text.Insert(textBox.SelectionStart, clipboardText);

            var evenOddConstraint = GetEvenOddConstraint(textBox);

            switch (GetOnlyNumeric(textBox))
            {
                case NumericFormat.Double:
                {
                    if (double.TryParse(newText, out double number))
                    {
                        switch (evenOddConstraint)
                        {
                            case EvenOddConstraint.OnlyEven:

                                if (number % 2 != 0)
                                    e.CancelCommand();

                                break;

                            case EvenOddConstraint.OnlyOdd:

                                if (number % 2 == 0)
                                    e.CancelCommand();

                                break;
                        }
                    }
                    else
                        e.CancelCommand();

                    break;
                }

                case NumericFormat.Int:
                {
                    if (int.TryParse(newText, out int number))
                    {
                        switch (evenOddConstraint)
                        {
                            case EvenOddConstraint.OnlyEven:

                                if (number % 2 != 0)
                                    e.CancelCommand();

                                break;

                            case EvenOddConstraint.OnlyOdd:

                                if (number % 2 == 0)
                                    e.CancelCommand();


                                break;
                        }
                    }
                    else
                        e.CancelCommand();

                    break;
                }

                case NumericFormat.Uint:
                {
                    if (uint.TryParse(newText, out uint number))
                    {
                        switch (evenOddConstraint)
                        {
                            case EvenOddConstraint.OnlyEven:

                                if (number % 2 != 0)
                                    e.CancelCommand();

                                break;

                            case EvenOddConstraint.OnlyOdd:

                                if (number % 2 == 0)
                                    e.CancelCommand();


                                break;
                        }
                    }
                    else
                        e.CancelCommand();

                    break;
                }

                case NumericFormat.Natural:
                {
                    if (uint.TryParse(newText, out uint number))
                    {
                        if (number == 0)
                            e.CancelCommand();
                        else
                        {
                            switch (evenOddConstraint)
                            {
                                case EvenOddConstraint.OnlyEven:

                                    if (number % 2 != 0)
                                        e.CancelCommand();

                                    break;

                                case EvenOddConstraint.OnlyOdd:

                                    if (number % 2 == 0)
                                        e.CancelCommand();

                                    break;
                            }
                        }
                    }
                    else
                    {
                        e.CancelCommand();
                    }

                    break;
                }
            }
        }
        else
        {
            e.CancelCommand();
        }
    }

    private static void TextBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        var textBox = (TextBox)sender;

        var defaultValue = GetDefaultValue(textBox);

        var evenOddConstraint = GetEvenOddConstraint(textBox);

        switch (GetOnlyNumeric(textBox))
        {
            case NumericFormat.Double:
            {
                if (double.TryParse(textBox.Text, out double number))
                {
                    switch (evenOddConstraint)
                    {
                        case EvenOddConstraint.OnlyEven:

                            if (number % 2 != 0)
                                textBox.Text = defaultValue;

                            break;

                        case EvenOddConstraint.OnlyOdd:

                            if (number % 2 == 0)
                                textBox.Text = defaultValue;

                            break;
                    }
                }
                else
                    textBox.Text = defaultValue;

                break;
            }

            case NumericFormat.Int:
            {
                if (int.TryParse(textBox.Text, out int number))
                {
                    switch (evenOddConstraint)
                    {
                        case EvenOddConstraint.OnlyEven:

                            if (number % 2 != 0)
                                textBox.Text = defaultValue;

                            break;

                        case EvenOddConstraint.OnlyOdd:

                            if (number % 2 == 0)
                                textBox.Text = defaultValue;

                            break;
                    }
                }
                else
                    textBox.Text = defaultValue;

                break;
            }

            case NumericFormat.Uint:
            {
                if (uint.TryParse(textBox.Text, out uint number))
                {
                    switch (evenOddConstraint)
                    {
                        case EvenOddConstraint.OnlyEven:

                            if (number % 2 != 0)
                                textBox.Text = defaultValue;

                            break;

                        case EvenOddConstraint.OnlyOdd:

                            if (number % 2 == 0)
                                textBox.Text = defaultValue;

                            break;
                    }
                }
                else
                    textBox.Text = defaultValue;

                break;
            }

            case NumericFormat.Natural:
            {
                if (uint.TryParse(textBox.Text, out uint number))
                {
                    if(number == 0)
                        textBox.Text = defaultValue;
                    else
                    {
                        switch (evenOddConstraint)
                        {
                            case EvenOddConstraint.OnlyEven:

                                if (number % 2 != 0)
                                    textBox.Text = defaultValue;

                                break;

                            case EvenOddConstraint.OnlyOdd:

                                if (number % 2 == 0)
                                    textBox.Text = defaultValue;

                                break;
                        }
                    }
                }
                else
                {
                    textBox.Text = defaultValue;
                }

                break;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是其简单用法的一些示例:

<TextBox viewHelpers:TextBoxHelper.OnlyNumeric="Double"
         viewHelpers:TextBoxHelper.DefaultValue="1"/>
Run Code Online (Sandbox Code Playgroud)

或者

<TextBox viewHelpers:TextBoxHelper.OnlyNumeric="Natural"
         viewHelpers:TextBoxHelper.DefaultValue="3"
         viewHelpers:TextBoxHelper.EvenOddConstraint="OnlyOdd"/>
Run Code Online (Sandbox Code Playgroud)

请注意,我的 TextBoxHelper 驻留在 viewHelpers xmlns 别名中。

我希望这个实现可以减轻其他人的工作:)

  • 很好的答案,但我发现您的方法难以阅读。也许你应该把它们分解成更小的。请参阅[您的方法的理想长度是多少?](https://softwareengineering.stackexchange.com/questions/133404/what-is-the-ideal-length-of-a-method-for-you) (4认同)

Ham*_*boh 8

我允许数字小键盘数字和退格:

    private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        int key = (int)e.Key;

        e.Handled = !(key >= 34 && key <= 43 || 
                      key >= 74 && key <= 83 || 
                      key == 2);
    }
Run Code Online (Sandbox Code Playgroud)

  • 我建议使用枚举值而不是**Magic Numbers**:`var keyEnum =(System.Windows.Input.Key)e.Key; e.Handled =!(keyEnum> = System.Windows.Input.Key.D0 && keyEnum <= System.Windows.Input.Key.D9 || keyEnum> = System.Windows.Input.Key.NumPad0 && keyEnum <= System .Windows.Input.Key.NumPad9 || keyEnum == System.Windows.Input.Key.Back);` (7认同)

小智 7

我会假设:

  1. 您要为其允许数字输入的TextBox仅将其Text属性设置为某个有效数字值(例如,2.7172).

  2. 您的文本框是主窗口的子项

  3. 您的主窗口是Window1类

  4. 您的TextBox名称是numericTB

基本理念:

  1. 添加:private string previousText;到您的主窗口类(Window1)

  2. 添加:previousText = numericTB.Text;到您的主窗口构造函数

  3. 为numericTB.TextChanged事件创建一个处理程序,如下所示:

    private void numericTB_TextChanged(object sender, TextChangedEventArgs e)
    {
        double num = 0;
        bool success = double.TryParse(((TextBox)sender).Text, out num);
        if (success & num >= 0)
            previousText = ((TextBox)sender).Text;
        else
            ((TextBox)sender).Text = previousText;
    }
    
    Run Code Online (Sandbox Code Playgroud)

只要它有效,这将继续将previousText设置为numericTB.Text,如果用户写了您不喜欢的内容,则将numericTB.Text设置为其最后一个有效值.当然,这只是基本的想法,它只是"白痴抗性",而不是"白痴证明".例如,它不处理用户混淆空间的情况.所以这是一个完整的解决方案,我认为是"白痴证明",如果我错了请告诉我:

  1. 您的Window1.xaml文件的内容:

    <Window x:Class="IdiotProofNumericTextBox.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
        <Grid>
            <TextBox Height="30" Width="100" Name="numericTB" TextChanged="numericTB_TextChanged"/>
        </Grid>
    </Window>
    
    Run Code Online (Sandbox Code Playgroud)
  2. Window.xaml.cs文件的内容:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace IdiotProofNumericTextBox
    {
        public partial class Window1 : Window
        {
            private string previousText;
    
            public Window1()
            {
                InitializeComponent();
                previousText = numericTB.Text;
            }
    
            private void numericTB_TextChanged(object sender, TextChangedEventArgs e)
            {
                if (string.IsNullOrEmpty(((TextBox)sender).Text))
                    previousText = "";
                else
                {
                    double num = 0;
                    bool success = double.TryParse(((TextBox)sender).Text, out num);
                    if (success & num >= 0)
                    {
                        ((TextBox)sender).Text.Trim();
                        previousText = ((TextBox)sender).Text;
                    }
                    else
                    {
                        ((TextBox)sender).Text = previousText;
                        ((TextBox)sender).SelectionStart = ((TextBox)sender).Text.Length;
                    }
                }
            }
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

就是这样.如果你有很多TextBox,那么我建议创建一个继承自TextBox的CustomControl,这样你就可以将previousText和numericTB_TextChanged包装在一个单独的文件中.


Eve*_*one 6

在 Windows 窗体中这很容易;您可以为按键添加一个事件,一切都会轻松进行。然而,在 WPF 中,该事件不存在。但有一种更简单的方法。

WPF TextBox 具有适用于所有内容的通用事件 TextChanged 事件。它包括粘贴、打字以及任何你能想到的事情。

所以你可以这样做:

XAML:

<TextBox name="txtBox1" ... TextChanged="TextBox_TextChanged"/>
Run Code Online (Sandbox Code Playgroud)

背后的代码:

private void TextBox_TextChanged(object sender, TextChangedEventArgs e) {
    string s = Regex.Replace(((TextBox)sender).Text, @"[^\d.]", "");
    ((TextBox)sender).Text = s;
}
Run Code Online (Sandbox Code Playgroud)

这也接受.,如果你不想要它,只需将其从regex声明中删除即可@[^\d]

注意:此事件可用于许多 TextBox 元素,因为它使用sender对象的文本。您只需编写该事件一次,即可将其用于多个 TextBox 元素。


iat*_*ato 6

如果您不想编写大量代码来执行基本功能(我不知道为什么人们会使用长方法),您可以这样做:

  1. 添加命名空间

    using System.Text.RegularExpressions;
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在XAML中,设置TextChanged属性:

    <TextBox x:Name="txt1" TextChanged="txt1_TextChanged"/>
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在txt1_TextChanged方法下的WPF中,添加Regex.Replace:

    private void txt1_TextChanged(object sender, TextChangedEventArgs e)
    {
        txt1.Text = Regex.Replace(txt1.Text, "[^0-9]+", "");
    }
    
    Run Code Online (Sandbox Code Playgroud)

  • 使用Behavior或AttachedProperty更加清晰.每个视图/每个文本框都没有代码隐藏的fiddeling (2认同)

Dan*_*ett 5

这是唯一需要的代码:

void MyTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
    e.Handled = new Regex("[^0-9]+").IsMatch(e.Text);
}
Run Code Online (Sandbox Code Playgroud)

这只允许将数字输入到文本框中.

要允许小数点或减号,可以将正则表达式更改为[^0-9.-]+.

  • 非常好的解决方案,除了一个小问题:它不会阻止您输入空格,因为它们不会触发 PreviewTextInput 事件。 (2认同)

Chr*_*ris 5

对于那些寻找仅使用整数和小数来快速且非常简单地实现此类问题的人,请在 XAML 文件中添加一个PreviewTextInput属性TextBox,然后在 xaml.cs 文件中使用:

private void Text_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
    e.Handled = !char.IsDigit(e.Text.Last()) && !e.Text.Last() == '.';
}
Run Code Online (Sandbox Code Playgroud)

每次都检查整个字符串有点多余,除非,正如其他人提到的,您正在使用科学记数法做一些事情(尽管,如果您要添加某些字符,例如“e”,则添加符号/字符的简单正则表达式是非常简单,并在其他答案中进行了说明)。但对于简单的浮点值,这个解决方案就足够了。

写成带有 lambda 表达式的单行代码:

private void Text_PreviewTextInput(object sender, TextCompositionEventArgs e) => e.Handled = !char.IsDigit(e.Text.Last() && !e.Text.Last() == '.');
Run Code Online (Sandbox Code Playgroud)


X S*_*ish 5

对于希望其文本字段仅接受无符号数字(例如套接字端口等)的开发人员:

WPF

<TextBox PreviewTextInput="Port_PreviewTextInput" MaxLines="1"/>
Run Code Online (Sandbox Code Playgroud)

C#

private void Port_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
    e.Handled = !int.TryParse(e.Text, out int x);
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,如果您确实想将此方法与套接字端口字段一起使用;您需要检查整数是否小于或等于“65535”。如果它更大,则它不是有效端口。此外,将“TextBox.MaxLength”设置为“5”将有助于*以编程方式或在 XAML 中*。 (3认同)