代码如下:
public class NumericBox : TextBox { public double Value { get => (double)GetValue(ValueProperty); set => SetValue(ValueProperty, value); } // Using a DependencyProperty as the backing store for Value. This enables animation, styling, binding, etc... public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(double), typeof(NumericBox), new FrameworkPropertyMetadata(double.NaN, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, (sender, e) => { if (sender is NumericBox numericBox && !double.IsNaN(numericBox.Value)) { if (numericBox.IsFocused && string.IsNullOrEmpty(numericBox.Text)) return; var text = numericBox.Value.ToString(); if (!numericBox.Text.Equals(text)) numericBox.Text = text; } })); private readonly Key[] _controlKeys ={ Key.Back, Key.CapsLock, Key.Down, Key.End, Key.Enter, Key.Escape, Key.Home, Key.Insert, Key.Left, Key.PageDown, Key.PageUp, Key.Right, Key.Tab, Key.Up, Key.Delete, }; public NumericBox() { MaxLines = 1; HorizontalContentAlignment = HorizontalAlignment.Center; VerticalContentAlignment = VerticalAlignment.Center; PreviewKeyDown += OnPreviewKeyDown; TextChanged += OnTextChanged; LostFocus += OnLostFocus; DataObject.AddPastingHandler(this, OnPasting); InputMethod.SetIsInputMethodEnabled(this, false); } / <summary> / 数值 / </summary> //public double Value { get; private set; } /// <summary> /// 是否是整数 /// </summary> public bool IsInteger { get; set; } /// <summary> /// 是否是正数 /// </summary> public bool IsPositive { get; set; } private void OnPreviewKeyDown(object sender, KeyEventArgs e) { if (IsControlKeys(e.Key)) return; if (IsDigit(e.Key)) return; if (!IsPositive && IsSubtract(e.Key)) { e.Handled = Text.Length > 0 && SelectionStart != 0; return; } if (!IsInteger && IsDot(e.Key)) { e.Handled = Text.Contains(".") || Text == "-"; return; } e.Handled = true; } private void OnTextChanged(object sender, TextChangedEventArgs e) { double.TryParse(Text, out var v); if (Value != v) Value = v; } private void OnPasting(object sender, DataObjectPastingEventArgs e) { if (e.DataObject.GetDataPresent(typeof(string))) { var text = e.DataObject.GetData(typeof(string)) as string; if (Text.Length > 0) text = Text.Insert(SelectionStart, text); if (double.TryParse(text, out var num)) return; } e.CancelCommand(); } private void OnLostFocus(object sender, RoutedEventArgs e) { if (string.IsNullOrEmpty(Text)) Text = Value.ToString(); } bool IsControlKeys(Key key) => _controlKeys.Contains(key); bool IsDigit(Key key) => ((Keyboard.Modifiers & ModifierKeys.Shift) == 0 && key >= Key.D0 && key <= Key.D9) || (key >= Key.NumPad0 && key <= Key.NumPad9); bool IsDot(Key key) => key == Key.Decimal || ((Keyboard.Modifiers & ModifierKeys.Shift) == 0 && key == Key.OemPeriod); bool IsSubtract(Key key) => key == Key.Subtract || ((Keyboard.Modifiers & ModifierKeys.Shift) == 0 && key == Key.OemMinus); }
