Wpf只能输入数字的TextBox

项目中有些场景比如参数输入只能输入数字,要么自己定义输入键盘,要么自己定义TextBox样式

这里采用自定义Textbox,比较简陋

样式效果

1.继承TextBox这里是看了,在此基础上修改的WPF自定义数字输入框控件 - 五好青年,勇往直前 - 博客园 (cnblogs.com)

  public string PMaxValue
  {
      get { return (string)GetValue(PMaxValueProperty); }
      set { SetValue(PMaxValueProperty, value); }
  }

  // Using a DependencyProperty as the backing store for MaxValue.  This enables animation, styling, binding, etc...
  public static readonly DependencyProperty PMaxValueProperty =
      DependencyProperty.Register("PMaxValue", typeof(string), typeof(HsTextBox), new PropertyMetadata(""));

  public string PMinValue
  {
      get { return (string)GetValue(PMinValueProperty); }
      set { SetValue(PMinValueProperty, value); }
  }

  // Using a DependencyProperty as the backing store for MaxValue.  This enables animation, styling, binding, etc...
  public static readonly DependencyProperty PMinValueProperty =
      DependencyProperty.Register("PMinValue", typeof(string), typeof(HsTextBox), new PropertyMetadata(""));




  public int PointLength
  {
      get { return (int)GetValue(PointLengthProperty); }
      set { SetValue(PointLengthProperty, value); }
  }

  // Using a DependencyProperty as the backing store for PointLength.  This enables animation, styling, binding, etc...
  public static readonly DependencyProperty PointLengthProperty =
      DependencyProperty.Register("PointLength", typeof(int), typeof(HsTextBox), new PropertyMetadata(3));





  public int NumberLength
  {
      get { return (int)GetValue(NumberLengthProperty); }
      set { SetValue(NumberLengthProperty, value); }
  }

  // Using a DependencyProperty as the backing store for NumberLength.  This enables animation, styling, binding, etc...
  public static readonly DependencyProperty NumberLengthProperty =
      DependencyProperty.Register("NumberLength", typeof(int), typeof(HsTextBox), new PropertyMetadata(7));
  private string val = "";



  protected override void OnKeyDown(KeyEventArgs e)
  {
      base.OnKeyDown(e);
      string txt = this.Text;
      int index = this.CaretIndex;
      if (Text.Contains("."))
      {
          if (txt.Split('.')[1].Length >= PointLength && index > txt.Split('.')[0].Length && this.SelectionLength == 0)//控制小数点后输入位数
          {
              e.Handled = true;
              return;
          }
          else if (txt.Split('.')[0].Length >= NumberLength && index <= txt.Split('.')[0].Length)//控制小数点前输入位数(有小数点)
          {
              e.Handled = true;
              return;
          }
      }
      else if (txt.Length == NumberLength && e.Key != Key.Decimal && e.Key != Key.OemPeriod)//控制小数点前输入位数(无小数点)
      {
          e.Handled = true;
          return;
      }


      //如果是句号就是.
      if (e.Key == Key.Decimal || e.Key == Key.OemPeriod)
      {
          val = ".";
      }
      else
      {

          val = "";
      }

      //屏蔽非法按键
      if ((e.Key >= Key.NumPad0 && e.Key <= Key.NumPad9) || e.Key == Key.Decimal || e.Key == Key.Subtract || e.Key.ToString() == "Tab")
      {
          if (txt.Contains(".") && e.Key == Key.Decimal)
          {
              e.Handled = true;
              return;
          }
          else if ((txt.Contains("-") || this.CaretIndex != 0) && e.Key == Key.Subtract)
          {
              e.Handled = true;
              return;
          }
          e.Handled = false;
      }
      else if (((e.Key >= Key.D0 && e.Key <= Key.D9) || e.Key == Key.OemPeriod || e.Key == Key.OemMinus) && e.KeyboardDevice.Modifiers != ModifierKeys.Shift)
      {
          if (txt.Contains(".") && e.Key == Key.OemPeriod)
          {
              e.Handled = true;
              return;
          }
          else if ((txt.Contains("-") || this.CaretIndex != 0) && e.Key == Key.OemMinus)
          {
              e.Handled = true;
              return;
          }
          e.Handled = false;
      }
      else if (e.Key == Key.Back || e.Key == Key.Delete)
      {
          var inde = txt.LastIndexOf(txt);
          txt.Remove(inde);
          e.Handled = true;
      }
      else if (e.Key == Key.Enter)
      {
          Osklib.OnScreenKeyboard.Close();
      }
      else
      {
          e.Handled = true;
          //this.Text = "";
          if (e.Key.ToString() != "RightCtrl")
          { }
      }

  }

  protected override void OnGotFocus(RoutedEventArgs e)
  {
      base.OnGotFocus(e);
      this.Select(this.Text.Length, 0);
  }

  protected override void OnPreviewTextInput(TextCompositionEventArgs e)
  {
      string txt = this.Text;
      string[] numberStr = new string[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "-", "." };
      string strs = string.Empty;
      for (int i = 0; i < txt.Length; i++)
      {
          if (numberStr.Contains(txt[i].ToString()))
          {
              strs += txt[i];
          };
      }
      if (strs.StartsWith(".", StringComparison.Ordinal))
      {
          strs = txt.Insert(0, "0");
      }
      this.Text = strs;
      this.Select(this.Text.Length, 0);
  }

  protected override void OnTextChanged(TextChangedEventArgs e)
  {
      string txt = this.Text;
      int index = this.CaretIndex;

      if (double.TryParse(txt, out double valu))
      {
          var v1 = double.TryParse(PMinValue, out double minv);
          var v2 = double.TryParse(PMaxValue, out double mmaxv);
          if (valu < minv)
          {
              var tmp1 = minv;
              this.Text = tmp1.ToString();
              e.Handled = true;
          }
          if (valu > mmaxv)
          {
              var tmp = mmaxv;
              this.Text = tmp.ToString();
              e.Handled = true;
          }
      }
      this.Text = this.Text.Trim();
      this.Select(this.Text.Length, 0);
  }
}

2.样式定义,验证样式

  <!--自定义数字框输入样式-->
  <Style TargetType="{x:Type hsct:HsTextBox}" x:Key="ValidationHsTextBoxStyle">
      <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
      <Setter Property="BorderBrush" Value="{StaticResource TextBox.Static.Border}"/>
      <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
      <Setter Property="BorderThickness" Value="1"/>
      <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
      <Setter Property="HorizontalContentAlignment" Value="Left"/>
      <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
      <Setter Property="AllowDrop" Value="true"/>
      <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
      <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
      <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
      <Setter Property="PMinValue" Value="{StaticResource ResourceKey=HsTextboxMinValue}"/>
      <Setter Property="PMaxValue" Value="{StaticResource ResourceKey=HsTextboxMaxValue}"/>
      <Setter Property="Template">
          <Setter.Value>
              <ControlTemplate TargetType="{x:Type TextBox}">
                  <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" 
                          BorderThickness="{TemplateBinding BorderThickness}"
                          Background="{TemplateBinding Background}" 
                          SnapsToDevicePixels="True"
                          CornerRadius="5">
                      <Grid>
                          <Border Name="root" Background="Transparent"></Border>
                          <ScrollViewer x:Name="PART_ContentHost"  Grid.Column="1" Focusable="false" 
                                VerticalAlignment="Center" Margin="5,0"
                                HorizontalScrollBarVisibility="Hidden"
                                VerticalScrollBarVisibility="Hidden"/>
                          <Popup  StaysOpen="True"  Name="Popp" 
                                PlacementTarget="{Binding ElementName=root}" AllowsTransparency="True"  Placement="Bottom"
                                VerticalOffset="0" HorizontalOffset="0" >
                              <TextBlock Text="{Binding Path=(Validation.Errors)[0].ErrorContent,RelativeSource={RelativeSource Mode=TemplatedParent}}" FontSize="14"
                                     Foreground="Red" VerticalAlignment="Center"
                                   HorizontalAlignment="Right" Margin="10,0" />
                          </Popup>
                      </Grid>
                  </Border>

                  <ControlTemplate.Triggers>
                      <Trigger Property="IsEnabled" Value="false">
                          <Setter Property="Opacity" TargetName="border" Value="0.56"/>
                      </Trigger>
                      <Trigger Property="AreAnyTouchesOver" Value="true">
                          <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.MouseOver.Border}"/>
                      </Trigger>
                      <Trigger Property="IsKeyboardFocused" Value="true">
                          <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.Focus.Border}"/>
                      </Trigger>
                      <Trigger Property="IsReadOnly" Value="True">
                          <Setter TargetName="border" Property="Background" Value="#F7F9FA"/>
                      </Trigger>
                      <Trigger Property="Validation.HasError" Value="True">
                          <Setter Property="IsOpen" Value="true" TargetName="Popp"/>
                      </Trigger>
                      <Trigger Property="Validation.HasError" Value="False">
                          <Setter Property="IsOpen" Value="False" TargetName="Popp"/>
                      </Trigger>
                  </ControlTemplate.Triggers>
              </ControlTemplate>
          </Setter.Value>
      </Setter>
      <Style.Triggers>
          <MultiTrigger>
              <MultiTrigger.Conditions>
                  <Condition Property="IsInactiveSelectionHighlightEnabled" Value="true"/>
                  <Condition Property="IsSelectionActive" Value="false"/>
              </MultiTrigger.Conditions>
              <Setter Property="SelectionBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
          </MultiTrigger>
      </Style.Triggers>
  </Style>

### 设置 WPF TextBox 仅允许输入数字 为了实现 WPF 中 `TextBox` 控件仅允许输入数字的功能,可以采用多种方式。一种常见的方式是在 XAML 文件中配置特定属性并处理相应的事件。 #### 方法一:通过正则表达式过滤字符 可以在 XAML 中定义 `TextBox` 并绑定其 `PreviewTextInput` 事件到后台代码中的处理器函数: ```xml <Window x:Class="wpfcore.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Grid> <!-- 定义一个文本框 --> <TextBox Name="numericTextBox" Width="150" Height="30" PreviewTextInput="NumericTextBox_PreviewTextInput"/> </Grid> </Window> ``` 对应的 C# 处理逻辑如下所示: ```csharp using System.Text.RegularExpressions; using System.Windows; namespace wpfcore { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void NumericTextBox_PreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e) { // 使用正则表达式判断输入是否为数字 e.Handled = !Regex.IsMatch(e.Text, "[0-9]"); } } } ``` 这种方法利用了正则表达式的强大模式匹配能力来验证用户的每一个按键输入[^3]。 #### 方法二:监听键盘按下事件 另一种方案是监听 `PreviewKeyDown` 事件,从而更精细地控制哪些键是可以被接受的。这种方式不仅限于阻止非数字字符,还可以灵活地加入其他特殊字符的支持,比如小数点或负号等。 下面是一个例子,它除了允许数字外还支持删除、退格以及方向键的操作,并额外加入了对分号的支持作为示范: ```xml <!-- 同样在XAML里声明文本框 --> <TextBox PreviewKeyDown="textBoxTrain_PreviewKeyDown"></TextBox> ``` 关联的 C# 实现如下: ```csharp private void textBoxTrain_PreviewKeyDown(object sender, KeyEventArgs e) { bool isValidKey = (e.Key >= Key.D0 && e.Key <= Key.D9) || // 数字键(顶部) (e.Key >= Key.NumPad0 && e.Key <= Key.NumPad9)|| // 小键盘上的数字 e.Key == Key.Delete || e.Key == Key.Back || e.Key == Key.Right || e.Key == Key.Left || e.Key == Key.OemSemicolon; // 英文分号 e.Handled = !isValidKey; } ``` 此段代码展示了如何基于不同的按键做出响应,确保只有指定类型的按键能够影响文本框的内容[^4]。 这两种方法都可以有效地限制用户只能向 `TextBox` 输入数字,开发者可以根据实际需求选择最合适的一种实施。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值