using System; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; namespace Elwig.Controls { public class IntegerUpDown : TextBox { public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register("Miminum", typeof(int?), typeof(IntegerUpDown), new FrameworkPropertyMetadata(null)); public int? Minimum { get => (int?)GetValue(MinimumProperty); set => SetValue(MinimumProperty, value); } public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register("Maximum", typeof(int?), typeof(IntegerUpDown), new FrameworkPropertyMetadata(null)); public int? Maximum { get => (int?)GetValue(MaximumProperty); set => SetValue(MaximumProperty, value); } public int? Value { get => int.TryParse(Text, out var res) ? res : null; set => Text = $"{value}"; } static IntegerUpDown() { DefaultStyleKeyProperty.OverrideMetadata(typeof(IntegerUpDown), new FrameworkPropertyMetadata(typeof(IntegerUpDown))); } public IntegerUpDown() { TextChanged += IntegerUpDown_TextChanged; LostFocus += IntegerUpDown_LostFocus; KeyUp += IntegerUpDown_KeyUp; } public override void OnApplyTemplate() { var incButton = GetTemplateChild("IncrementButton") as RepeatButton; var decButton = GetTemplateChild("DecrementButton") as RepeatButton; incButton!.Click += IncrementButton_Click; decButton!.Click += DecrementButton_Click; base.OnApplyTemplate(); } private void IntegerUpDown_TextChanged(object sender, TextChangedEventArgs evt) { var idx = CaretIndex; Text = new string(Text.Where(char.IsAsciiDigit).Take(4).ToArray()); CaretIndex = idx; evt.Handled = !(Value >= Minimum && Value <= Maximum); if (idx >= 4) { if (Value < Minimum) { Value = Minimum; } else if (Value > Maximum) { Value = Maximum; } CaretIndex = 4; } } private void IntegerUpDown_LostFocus(object sender, RoutedEventArgs evt) { if (Value < Minimum) { Value = Minimum; } else if (Value > Maximum) { Value = Maximum; } } private void IncrementButton_Click(object sender, RoutedEventArgs evt) { Value = Math.Min((Value ?? 0) + 1, Maximum ?? int.MaxValue); } private void DecrementButton_Click(object sender, RoutedEventArgs evt) { Value = Math.Max((Value ?? 0) - 1, Minimum ?? int.MinValue); } private void IntegerUpDown_KeyUp(object sender, KeyEventArgs evt) { switch (evt.Key) { case Key.Up: case Key.Add: case Key.OemPlus: Value = Math.Min((Value ?? 0) + 1, Maximum ?? int.MaxValue); evt.Handled = true; CaretIndex = 4; break; case Key.Down: case Key.Subtract: case Key.OemMinus: Value = Math.Max((Value ?? 0) - 1, Minimum ?? int.MinValue); evt.Handled = true; CaretIndex = 4; break; case Key.PageUp: Value = Math.Min((Value ?? 0) + 10, Maximum ?? int.MaxValue); evt.Handled = true; CaretIndex = 4; break; case Key.PageDown: Value = Math.Max((Value ?? 0) - 10, Minimum ?? int.MinValue); evt.Handled = true; CaretIndex = 4; break; } } } }