diff --git a/src/MaterialDesignThemes.Wpf/UpDownBase.cs b/src/MaterialDesignThemes.Wpf/UpDownBase.cs index 0617eb7824..f16e6afc35 100644 --- a/src/MaterialDesignThemes.Wpf/UpDownBase.cs +++ b/src/MaterialDesignThemes.Wpf/UpDownBase.cs @@ -47,6 +47,8 @@ private static bool TryParse(string text, IFormatProvider? formatProvider, [NotN private static int Compare(T value1, T value2) => _arithmetic.Compare(value1, value2); #endif + private bool _isTextChanging; + #region DependencyProperties #region DependencyProperty : MinimumProperty @@ -116,7 +118,7 @@ private static void OnNumericValueChanged(DependencyObject d, DependencyProperty }; upDownBase.RaiseEvent(args); - if (upDownBase._textBoxField is { } textBox) + if (!upDownBase._isTextChanging && upDownBase._textBoxField is { } textBox) { textBox.Text = Convert.ToString(e.NewValue, CultureInfo.CurrentCulture); } @@ -196,10 +198,13 @@ public event RoutedPropertyChangedEventHandler ValueChanged public override void OnApplyTemplate() { if (_increaseButton != null) + { _increaseButton.Click -= IncreaseButtonOnClick; - + } if (_decreaseButton != null) + { _decreaseButton.Click -= DecreaseButtonOnClick; + } if (_textBoxField != null) { _textBoxField.TextChanged -= OnTextBoxTextChanged; @@ -243,7 +248,9 @@ private void OnTextBoxTextChanged(object sender, EventArgs e) { if (TryParse(textBoxField.Text, CultureInfo.CurrentCulture, out T? value)) { + _isTextChanging = true; SetCurrentValue(ValueProperty, ClampValue(value)); + _isTextChanging = false; } } } diff --git a/tests/MaterialDesignThemes.UITests/WPF/UpDownControls/NumericUpDownTests.cs b/tests/MaterialDesignThemes.UITests/WPF/UpDownControls/NumericUpDownTests.cs index c0f2d8f317..21a5ef4553 100644 --- a/tests/MaterialDesignThemes.UITests/WPF/UpDownControls/NumericUpDownTests.cs +++ b/tests/MaterialDesignThemes.UITests/WPF/UpDownControls/NumericUpDownTests.cs @@ -213,6 +213,30 @@ public async Task NumericUpDown_WhenBindingUpdateTriggerIsPropertyChanged_ItUpda await Assert.That(tag?.ToString()).IsEqualTo("4"); } + [Test] + [Description("Issue 4061")] + public async Task NumericUpDown_WhenMinimumIsPositiveNumber_ItAllowsTextToBeChangedWithoutClamping() + { + //Arrange + //NB: Value should be something that is not equal to the minimum + var numericUpDown = await LoadXaml(""" + + """); + + var textBox = await numericUpDown.GetElement("PART_TextBox"); + + //Act + await textBox.MoveKeyboardFocus(); + await textBox.SendKeyboardInput($"{ModifierKeys.Control}{Key.A}{ModifierKeys.None}8"); + object? firstValue = await numericUpDown.GetTag(); + await textBox.SendKeyboardInput($"7"); + object? secondValue = await numericUpDown.GetTag(); + + //Assert + await Assert.That(firstValue?.ToString()).IsEqualTo("60"); + await Assert.That(secondValue?.ToString()).IsEqualTo("87"); + } + [Test] [Description("Issue 3827")] public async Task NumericUpDown_WhenBindingUpdateTriggerIsLostFocus_ItDoesNotUpdateUntilItLoosesFocus()