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(nameof(Minimum), 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(nameof(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(); UpdateButtons(); } private void UpdateButtons() { var incButton = GetTemplateChild("IncrementButton") as RepeatButton; var decButton = GetTemplateChild("DecrementButton") as RepeatButton; incButton?.IsEnabled = Maximum == null || Value < Maximum; decButton?.IsEnabled = Minimum == null || Value > Minimum; } private void IntegerUpDown_TextChanged(object sender, TextChangedEventArgs evt) { var idx = CaretIndex; Text = new string([.. Text.Where(char.IsAsciiDigit).Take(4)]); CaretIndex = idx; evt.Handled = !((!Minimum.HasValue || Value >= Minimum) && (!Maximum.HasValue || Value <= Maximum)); if (idx >= 4) { if (Value < Minimum) { Value = Minimum; } else if (Value > Maximum) { Value = Maximum; } CaretIndex = 4; } UpdateButtons(); } 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; } } } }