Bootstrap

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>

;