【问题标题】:Create WPF TextBox that accepts only numbers [duplicate]创建仅接受数字的 WPF TextBox [重复]
【发布时间】:2023-03-20 02:16:02
【问题描述】:

我想创建一个只接受特定范围内数值的文本框。 实现此类 TextBox 的最佳方法是什么?

我想过派生 TextBox 并覆盖 TextProperty 的验证和强制。但是,我不确定如何执行此操作,并且我知道通常不建议派生 WPF 控件。


编辑:
我需要的是一个非常基本的文本框,它可以过滤掉所有不是数字的按键。 实现它的最简单方法是处理 TextBox.PreviewTextInput 事件:
private void textBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
    int result;
    if (!validateStringAsNumber(e.Text,out result,false))
    {
        e.Handled = true;
    }
}

(validateStringAsNumber 是我主要使用 Int.TryParse 的函数)

一些建议的解决方案可能更好,但对于我需要的简单功能,这个解决方案是最容易和最快实施的,同时足以满足我的需求。

【问题讨论】:

标签: c# wpf textbox


【解决方案1】:

到目前为止,我看到的大多数实现都是使用PreviewTextInput 事件来实现正确的掩码行为。 This one 继承自 TextBox,this one 使用附加属性。两者都使用 .Net 的 MaskedTextProvider 来提供正确的掩码行为,但如果您只想要一个简单的“仅限数字”文本框,则不需要此类。

【讨论】:

    【解决方案2】:
    private void txt_TextChanged(object sender, TextChangedEventArgs e)
    {
        TextBox textBox = sender as TextBox;
        int iValue = -1;
    
        if (Int32.TryParse(textBox.Text, out iValue) == false)
        {
             TextChange textChange = e.Changes.ElementAt<TextChange>(0);
             int iAddedLength = textChange.AddedLength;
             int iOffset = textChange.Offset;
    
             textBox.Text = textBox.Text.Remove(iOffset, iAddedLength);
        }
    }
    

    【讨论】:

    • 当我使用上面的代码时,我检索到错误消息:“错误 1 ​​'System.Collections.Generic.ICollection' 不包含 'ElementAt' 的定义和找不到接受“System.Collections.Generic.ICollection”类型的第一个参数的扩展方法“ElementAt”(您是否缺少 using 指令或程序集引用?)NewProduct.xaml。 cs 104 51 MediaStore" 缺少什么参考?
    • @Legato 可能不同的 .net 框架
    【解决方案3】:

    以我的拙见,满足此要求的最佳方法是仅使用OnTextChanged 事件,因为它可以处理按键中的数字,也可以处理剪贴板中的复制+粘贴。我希望下面显示的 VB 代码可以对此有所了解。

    Private Sub NumericBox_TextChanged(sender As Object, e As TextChangedEventArgs) Handles Me.TextChanged
      Dim Buffer As New StringBuilder
      Dim Index As Integer = Me.SelectionStart
      For Each C In Me.Text
        If Char.IsDigit(C) Then
          Buffer.Append(C)
        ElseIf Me.SelectionStart > Buffer.Length Then
          Index -= 1
        End If
      Next
      Me.Text = Buffer.ToString
      Me.SelectionStart = Index
    End Sub
    

    【讨论】:

      【解决方案4】:

      总体上最好的原因是对文本框使用覆盖方法OnKeyPressed。这是使用静态字符方法IsDigit 进行覆盖的代码。

      if (!Char.IsDigit(e.KeyChar) && !Char.IsControl(e.KeyChar)) e.Handled = true;
      

      这就是你真正需要做的。

      【讨论】:

      • 唯一的问题是它不允许你使用小数点 (.)
      • TextBox 只有 KeyDownPreviewKeyDown 事件,它们发送参数为 KeyEventArgs 。并且这不包含 KeyChar 仅属性 Key 属性,它从 Keys 枚举返回一个
      • 另外,如果有人想从剪贴板粘贴一个数字怎么办?
      【解决方案5】:

      这将是我的首选方法:

      private void yearTxt_PreviewKeyDown(object sender, KeyEventArgs e)
      {
        switch (e.Key)
        {
          case Key.D0:
          case Key.D1:
          case Key.D2:
          case Key.D3:
          case Key.D4:
          case Key.D5:
          case Key.D6:
          case Key.D7:
          case Key.D8:
          case Key.D9:
          case Key.NumLock:
          case Key.NumPad0:
          case Key.NumPad1:
          case Key.NumPad2:
          case Key.NumPad3:
          case Key.NumPad4:
          case Key.NumPad5:
          case Key.NumPad6:
          case Key.NumPad7:
          case Key.NumPad8:
          case Key.NumPad9:
          case Key.Back:
            break;
          default:
            e.Handled = true;
            break;
        }
      }
      

      【讨论】:

      • 如果您经常使用数字文本框并且不想重复代码很多,您可以这样做: 1. 通过将Bryuns 代码重命名为“numericTextBox”或类似名称来创建一个方法。 2. 像这样调用“PreviewKeyDown”事件中的方法: private void textBox1_PreviewKeyDown(object sender, KeyEventArgs e) { numericTextBox(sender, e); }
      • 这不处理粘贴的文本或用户修改数字键和键入 $%^ 等字符。此外,用户不能使用箭头键移动插入符号。
      猜你喜欢
      • 2021-10-22
      • 1970-01-01
      • 2016-09-14
      • 1970-01-01
      • 1970-01-01
      • 2013-01-26
      • 1970-01-01
      • 2013-12-15
      • 1970-01-01
      相关资源
      最近更新 更多