WPF中文本框的验证

10

我目前正在开发一个WPF应用程序,我想要一个TextBox只能输入数字。我知道当失去焦点时可以验证其内容并阻止内容为数字,但在其他Windows表单应用程序中,我们通常会完全阻止除数字以外的任何输入。此外,我们会将该代码放在单独的dll中以便在多个地方引用。

以下是2008年没有使用WPF的代码:

Public Shared Sub BloquerInt(ByRef e As System.Windows.Forms.KeyPressEventArgs, ByRef oTxt As Windows.Forms.TextBox, ByVal intlongueur As Integer)
    Dim intLongueurSelect As Integer = oTxt.SelectionLength
    Dim intPosCurseur As Integer = oTxt.SelectionStart
    Dim strValeurTxtBox As String = oTxt.Text.Substring(0, intPosCurseur) & oTxt.Text.Substring(intPosCurseur + intLongueurSelect, oTxt.Text.Length - intPosCurseur - intLongueurSelect)

    If IsNumeric(e.KeyChar) OrElse _
       Microsoft.VisualBasic.Asc(e.KeyChar) = System.Windows.Forms.Keys.Back Then
        If Microsoft.VisualBasic.AscW(e.KeyChar) = System.Windows.Forms.Keys.Back Then
            e.Handled = False
        ElseIf strValeurTxtBox.Length < intlongueur Then
            e.Handled = False
        Else
            e.Handled = True

        End If
    Else
        e.Handled = True
    End If

在WPF中有没有对应的方式?如果是在样式中也没关系,但我刚接触WPF,对样式的了解还不够充分。

2个回答

23

您可以使用 TextBox 上的附加属性将输入限制为仅数字。只需定义一次附加属性(甚至可以在单独的 dll 中),然后在任何 TextBox 上使用它。以下是该附加属性:

   using System;
   using System.Windows;
   using System.Windows.Controls;
   using System.Windows.Input;

   /// <summary>
   /// Class that provides the TextBox attached property
   /// </summary>
   public static class TextBoxService
   {
      /// <summary>
      /// TextBox Attached Dependency Property
      /// </summary>
      public static readonly DependencyProperty IsNumericOnlyProperty = DependencyProperty.RegisterAttached(
         "IsNumericOnly",
         typeof(bool),
         typeof(TextBoxService),
         new UIPropertyMetadata(false, OnIsNumericOnlyChanged));

      /// <summary>
      /// Gets the IsNumericOnly property.  This dependency property indicates the text box only allows numeric or not.
      /// </summary>
      /// <param name="d"><see cref="DependencyObject"/> to get the property from</param>
      /// <returns>The value of the StatusBarContent property</returns>
      public static bool GetIsNumericOnly(DependencyObject d)
      {
         return (bool)d.GetValue(IsNumericOnlyProperty);
      }

      /// <summary>
      /// Sets the IsNumericOnly property.  This dependency property indicates the text box only allows numeric or not.
      /// </summary>
      /// <param name="d"><see cref="DependencyObject"/> to set the property on</param>
      /// <param name="value">value of the property</param>
      public static void SetIsNumericOnly(DependencyObject d, bool value)
      {
         d.SetValue(IsNumericOnlyProperty, value);
      }

      /// <summary>
      /// Handles changes to the IsNumericOnly property.
      /// </summary>
      /// <param name="d"><see cref="DependencyObject"/> that fired the event</param>
      /// <param name="e">A <see cref="DependencyPropertyChangedEventArgs"/> that contains the event data.</param>
      private static void OnIsNumericOnlyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
      {
         bool isNumericOnly = (bool)e.NewValue;

         TextBox textBox = (TextBox)d;

         if (isNumericOnly)
         {
            textBox.PreviewTextInput += BlockNonDigitCharacters;
            textBox.PreviewKeyDown += ReviewKeyDown;
         }
         else
         {
            textBox.PreviewTextInput -= BlockNonDigitCharacters;
            textBox.PreviewKeyDown -= ReviewKeyDown;
         }
      }

      /// <summary>
      /// Disallows non-digit character.
      /// </summary>
      /// <param name="sender">The source of the event.</param>
      /// <param name="e">An <see cref="TextCompositionEventArgs"/> that contains the event data.</param>
      private static void BlockNonDigitCharacters(object sender, TextCompositionEventArgs e)
      {
         foreach (char ch in e.Text)
         {
            if (!Char.IsDigit(ch))
            {
               e.Handled = true;
            }
         }
      }

      /// <summary>
      /// Disallows a space key.
      /// </summary>
      /// <param name="sender">The source of the event.</param>
      /// <param name="e">An <see cref="KeyEventArgs"/> that contains the event data.</param>
      private static void ReviewKeyDown(object sender, KeyEventArgs e)
      {
         if (e.Key == Key.Space)
         {
            // Disallow the space key, which doesn't raise a PreviewTextInput event.
            e.Handled = true;
         }
      }
   }

这里是如何使用它的方法(将“controls”替换为您自己的命名空间):
<TextBox controls:TextBoxService.IsNumericOnly="True" />

1
我会尝试。我想像可以虚拟地添加任何类似的东西。例如,文本内部的最大长度,这也是我遇到的另一个问题。 - David Brunelle
忘了提到,这是浮点数的最大长度(小数部分的最大位数和整数部分的最大位数)。 - David Brunelle
1
是的,附加属性非常强大,可以让您添加各种类型的行为。 - John Myczek
提示: BlockNonDigitCharacters方法可以进行优化,代码如下: if (e.Text.Any(ch => !Char.IsDigit(ch))) e.Handled = true; - Paw Baltzersen
这个解决方案充其量是不完整的。它不能处理使用Ctrl+V或上下文菜单从剪贴板粘贴,也不能处理用鼠标拖动文本的情况。楼主的代码同样存在缺陷,但这并不能让这段代码变得更好。在修复之前给予-1。 - Ivan Danilov

4
您可以在绑定中加入验证。
<TextBox>
         <TextBox.Text>
              <Binding Path="CategoriaSeleccionada.ColorFondo"
                       UpdateSourceTrigger="PropertyChanged">
                     <Binding.ValidationRules>
                           <utilities:RGBValidationRule />
                     </Binding.ValidationRules>
               </Binding>
         </TextBox.Text>
</TextBox>

看这个例子(我的程序),你可以把验证放在绑定里面,就像这样。使用UpdateSourceTrigger,你可以改变绑定何时更新(失去焦点,在每次更改中...)

好的,验证是一个类,我将给你一个示例:

class RGBValidationRule : ValidationRule
{
    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        // Here you make your validation using the value object.
        // If you want to check if the object is only numbers you can
        // Use some built-in method
        string blah = value.ToString();
        int num;
        bool isNum = int.TryParse(blah, out num);

        if (isNum) return new ValidationResult(true, null);
        else return new ValidationResult(false, "It's no a number");
    }
}

简而言之,在该方法内执行任务并返回新的ValidationResult。第一个参数是布尔值,如果验证成功为true,否则为false。第二个参数仅作为信息的消息。
我认为这是文本框验证的基础知识。
希望这有所帮助。
编辑:抱歉,我不懂VB.NET,但我认为C#代码非常简单。

我两种都懂,所以对我来说很容易转换它。谢谢,我会尽快尝试的。 - David Brunelle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接