diff --git a/src/MahApps.Metro.Samples/MahApps.Metro.Demo/ExampleViews/TextExamples.xaml b/src/MahApps.Metro.Samples/MahApps.Metro.Demo/ExampleViews/TextExamples.xaml
index cac99344a6..f73cee2ac2 100644
--- a/src/MahApps.Metro.Samples/MahApps.Metro.Demo/ExampleViews/TextExamples.xaml
+++ b/src/MahApps.Metro.Samples/MahApps.Metro.Demo/ExampleViews/TextExamples.xaml
@@ -324,316 +324,207 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ 2
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
this.Set(ref this.currentCulture, value);
}
- private double? numericUpDownValue = null;
+ private double numericUpDownValue = default;
- public double? NumericUpDownValue
+ public double NumericUpDownValue
{
get => this.numericUpDownValue;
set => this.Set(ref this.numericUpDownValue, value);
}
+ private double? nullableNumericUpDownValue = null;
+
+ public double? NullableNumericUpDownValue
+ {
+ get => this.nullableNumericUpDownValue;
+ set => this.Set(ref this.nullableNumericUpDownValue, value);
+ }
+
+
public ICommand EndOfScrollReachedCmdWithParameter { get; }
public int? IntegerGreater10Property
diff --git a/src/MahApps.Metro/Controls/NumericUpDown.cs b/src/MahApps.Metro/Controls/NumericUpDown.cs
index 462d6273b2..0b62e43534 100644
--- a/src/MahApps.Metro/Controls/NumericUpDown.cs
+++ b/src/MahApps.Metro/Controls/NumericUpDown.cs
@@ -378,32 +378,32 @@ private static void OnValuePropertyChanged(DependencyObject dependencyObject, De
}
[MustUseReturnValue]
- private static object? CoerceValue(DependencyObject d, object? value)
+ private static object? CoerceValue(DependencyObject d, object? baseValue)
{
- if (value is null)
+ var numericUpDown = (NumericUpDown)d;
+ if (baseValue is null)
{
- return null;
+ return numericUpDown.DefaultValue;
}
- var numericUpDown = (NumericUpDown)d;
- double val = ((double?)value).Value;
+ var value = ((double?)baseValue).Value;
if (!numericUpDown.NumericInputMode.HasFlag(NumericInput.Decimal))
{
- val = Math.Truncate(val);
+ value = Math.Truncate(value);
}
- if (val < numericUpDown.Minimum)
+ if (value < numericUpDown.Minimum)
{
return numericUpDown.Minimum;
}
- if (val > numericUpDown.Maximum)
+ if (value > numericUpDown.Maximum)
{
return numericUpDown.Maximum;
}
- return val;
+ return value;
}
///
@@ -418,6 +418,56 @@ private static void OnValuePropertyChanged(DependencyObject dependencyObject, De
set => this.SetValue(ValueProperty, value);
}
+ /// Identifies the dependency property.
+ public static readonly DependencyProperty DefaultValueProperty
+ = DependencyProperty.Register(nameof(DefaultValue),
+ typeof(double?),
+ typeof(NumericUpDown),
+ new PropertyMetadata(null, OnDefaultValuePropertyChanged, CoerceDefaultValue));
+
+ private static void OnDefaultValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var numericUpDown = (NumericUpDown)d;
+
+ if (!numericUpDown.Value.HasValue && numericUpDown.DefaultValue.HasValue)
+ {
+ numericUpDown.SetValueTo(numericUpDown.DefaultValue.Value);
+ }
+ }
+
+ [MustUseReturnValue]
+ private static object? CoerceDefaultValue(DependencyObject d, object? baseValue)
+ {
+ if (baseValue is double val)
+ {
+ var minimum = ((NumericUpDown)d).Minimum;
+ var maximum = ((NumericUpDown)d).Maximum;
+
+ if (val < minimum)
+ {
+ return minimum;
+ }
+ else if (val > maximum)
+ {
+ return maximum;
+ }
+ }
+
+ return baseValue;
+ }
+
+ ///
+ /// Gets or sets the default value of the NumericUpDown which will be used if the is .
+ ///
+ [Bindable(true)]
+ [Category("Common")]
+ [DefaultValue(null)]
+ public double? DefaultValue
+ {
+ get => (double?)this.GetValue(DefaultValueProperty);
+ set => this.SetValue(DefaultValueProperty, value);
+ }
+
/// Identifies the dependency property.
public static readonly DependencyProperty MinimumProperty
= DependencyProperty.Register(nameof(Minimum),
@@ -431,6 +481,7 @@ private static void OnMinimumPropertyChanged(DependencyObject d, DependencyPrope
numericUpDown.CoerceValue(MaximumProperty);
numericUpDown.CoerceValue(ValueProperty);
+ numericUpDown.CoerceValue(DefaultValueProperty);
numericUpDown.OnMinimumChanged((double)e.OldValue, (double)e.NewValue);
numericUpDown.EnableDisableUpDown();
}
@@ -459,6 +510,7 @@ private static void OnMaximumPropertyChanged(DependencyObject d, DependencyPrope
var numericUpDown = (NumericUpDown)d;
numericUpDown.CoerceValue(ValueProperty);
+ numericUpDown.CoerceValue(DefaultValueProperty);
numericUpDown.OnMaximumChanged((double)e.OldValue, (double)e.NewValue);
numericUpDown.EnableDisableUpDown();
}
@@ -1432,6 +1484,10 @@ private void ChangeValueFromTextInput(TextBox? textBox)
convertedValue = FormattedValue(convertedValue, this.StringFormat, this.SpecificCultureInfo);
this.SetValueTo(convertedValue);
}
+ else if (this.DefaultValue.HasValue)
+ {
+ this.SetValueTo(this.DefaultValue.Value);
+ }
}
this.OnValueChanged(this.Value, this.Value);
@@ -1446,7 +1502,18 @@ private void OnTextChanged(object sender, TextChangedEventArgs e)
if (string.IsNullOrEmpty(((TextBox)sender).Text))
{
- this.Value = null;
+ if (this.DefaultValue.HasValue)
+ {
+ this.SetValueTo(this.DefaultValue.Value);
+ if (!this.manualChange)
+ {
+ this.InternalSetText(this.DefaultValue.Value);
+ }
+ }
+ else
+ {
+ this.SetCurrentValue(ValueProperty, null);
+ }
}
else if (this.manualChange || e.UndoAction == UndoAction.Undo || e.UndoAction == UndoAction.Redo)
{
diff --git a/src/Mahapps.Metro.Tests/Tests/NumericUpDownTests.cs b/src/Mahapps.Metro.Tests/Tests/NumericUpDownTests.cs
index 59836ca1ae..1f0315d9c4 100644
--- a/src/Mahapps.Metro.Tests/Tests/NumericUpDownTests.cs
+++ b/src/Mahapps.Metro.Tests/Tests/NumericUpDownTests.cs
@@ -331,5 +331,45 @@ private static void SetText(TextBox theTextBox, string theText)
theTextBox.RaiseEvent(textCompositionEventArgs);
theTextBox.RaiseEvent(new RoutedEventArgs(UIElement.LostFocusEvent));
}
+
+ [Fact]
+ public async Task ShouldSetDefaultValue()
+ {
+ // Prepare
+ await this.fixture.PrepareForTestAsync().ConfigureAwait(true);
+ await TestHost.SwitchToAppThread();
+
+ var nud = this.fixture.Window.TheNUD;
+ nud.Minimum = 0;
+ nud.Maximum = 10;
+
+ // 1. Test: The default value must be set here. Let's check this.
+
+ nud.DefaultValue = 1;
+ nud.Value = null;
+
+ Assert.Equal(nud.Value, nud.DefaultValue);
+
+ // 2. Test: There is no default value, so we should be able to set it to null
+
+ nud.DefaultValue = null;
+ nud.Value = null;
+
+ Assert.Equal(nud.Value, nud.DefaultValue);
+
+ // 3. Test: We set the Default Value greater than the Maximum. It should be corrected by the control
+ nud.DefaultValue = 100;
+ nud.Value = null;
+
+ Assert.Equal(nud.Maximum, nud.DefaultValue);
+ Assert.Equal(nud.Maximum, nud.Value);
+
+ // 4. Test: We set the Default Value lower than the Minimum. It should be corrected by the control
+ nud.DefaultValue = -100;
+ nud.Value = null;
+
+ Assert.Equal(nud.Minimum, nud.DefaultValue);
+ Assert.Equal(nud.Minimum, nud.Value);
+ }
}
}
\ No newline at end of file