diff --git a/MahApps.Metro/Controls/NumericUpDown.cs b/MahApps.Metro/Controls/NumericUpDown.cs
index a83eb2d31e..9e285fee88 100644
--- a/MahApps.Metro/Controls/NumericUpDown.cs
+++ b/MahApps.Metro/Controls/NumericUpDown.cs
@@ -33,7 +33,7 @@ public class NumericUpDown : Control
public static readonly DependencyProperty DelayProperty = DependencyProperty.Register("Delay",
typeof(int),
typeof(NumericUpDown),
- new FrameworkPropertyMetadata(DefaultDelay, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnDelayChanged),
+ new FrameworkPropertyMetadata(DefaultDelay, OnDelayChanged),
ValidateDelay);
public static readonly DependencyProperty TextAlignmentProperty = TextBox.TextAlignmentProperty.AddOwner(typeof(NumericUpDown));
@@ -41,15 +41,41 @@ public class NumericUpDown : Control
public static readonly DependencyProperty SpeedupProperty = DependencyProperty.Register("Speedup",
typeof(bool),
typeof(NumericUpDown),
- new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSpeedupChanged));
-
- public static readonly DependencyProperty IsReadOnlyProperty = TextBoxBase.IsReadOnlyProperty.AddOwner(typeof(NumericUpDown), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits));
- public static readonly DependencyProperty StringFormatProperty = DependencyProperty.Register("StringFormat", typeof(string), typeof(NumericUpDown), new FrameworkPropertyMetadata(null, OnStringFormatChanged));
- public static readonly DependencyProperty InterceptArrowKeysProperty = DependencyProperty.Register("InterceptArrowKeys", typeof(bool), typeof(NumericUpDown), new FrameworkPropertyMetadata(true));
- public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(double?), typeof(NumericUpDown), new FrameworkPropertyMetadata(default(double?), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnValueChanged, CoerceValue));
- public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register("Minimum", typeof(double), typeof(NumericUpDown), new FrameworkPropertyMetadata(double.MinValue, OnMinimumChanged));
- public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register("Maximum", typeof(double), typeof(NumericUpDown), new FrameworkPropertyMetadata(double.MaxValue, OnMaximumChanged, CoerceMaximum));
- public static readonly DependencyProperty IntervalProperty = DependencyProperty.Register("Interval", typeof(double), typeof(NumericUpDown), new PropertyMetadata((double)1, IntervalChanged));
+ new FrameworkPropertyMetadata(true, OnSpeedupChanged));
+
+ public static readonly DependencyProperty IsReadOnlyProperty = TextBoxBase.IsReadOnlyProperty.AddOwner(typeof(NumericUpDown),
+ new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits));
+
+ public static readonly DependencyProperty StringFormatProperty = DependencyProperty.Register("StringFormat",
+ typeof(string),
+ typeof(NumericUpDown),
+ new FrameworkPropertyMetadata(string.Empty, OnStringFormatChanged, CoerceStringFormat));
+
+ public static readonly DependencyProperty InterceptArrowKeysProperty = DependencyProperty.Register("InterceptArrowKeys",
+ typeof(bool),
+ typeof(NumericUpDown),
+ new FrameworkPropertyMetadata(true));
+
+ public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value",
+ typeof(double?),
+ typeof(NumericUpDown),
+ new FrameworkPropertyMetadata(default(double?), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnValueChanged, CoerceValue));
+
+ public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register("Minimum",
+ typeof(double),
+ typeof(NumericUpDown),
+ new FrameworkPropertyMetadata(double.MinValue, OnMinimumChanged));
+
+ public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register("Maximum",
+ typeof(double),
+ typeof(NumericUpDown),
+ new FrameworkPropertyMetadata(double.MaxValue, OnMaximumChanged, CoerceMaximum));
+
+ public static readonly DependencyProperty IntervalProperty = DependencyProperty.Register("Interval",
+ typeof(double),
+ typeof(NumericUpDown),
+ new FrameworkPropertyMetadata(DefaultInterval, IntervalChanged));
+
private const double DefaultInterval = 1d;
private const int DefaultDelay = 500;
private const string ElementNumericDown = "PART_NumericDown";
@@ -59,7 +85,7 @@ public class NumericUpDown : Control
#endregion
private double _internalIntervalMultiplierForCalculation = DefaultInterval;
- private double _internalLargeChange;
+ private double _internalLargeChange = DefaultInterval * 100;
private double _intervalValueSinceReset;
private bool _manualChange;
private RepeatButton _repeatDown;
@@ -127,11 +153,12 @@ public event RoutedEventHandler DelayChanged
///
/// Gets or sets the amount of time, in milliseconds, the NumericUpDown waits while the up/down button is pressed
/// before it starts increasing/decreasing the
- /// for the specified . The value must be
+ /// for the specified . The value must be
/// non-negative.
///
+ [Bindable(true)]
[DefaultValue(DefaultDelay)]
- [Category("Common")]
+ [Category("Behavior")]
public int Delay
{
get { return (int)GetValue(DelayProperty); }
@@ -141,12 +168,18 @@ public int Delay
///
/// Gets or sets a value indicating whether the user can use the UP ARROW and DOWN ARROW keys to select values.
///
+ [Bindable(true)]
+ [Category("Behavior")]
+ [DefaultValue(true)]
public bool InterceptArrowKeys
{
get { return (bool)GetValue(InterceptArrowKeysProperty); }
set { SetValue(InterceptArrowKeysProperty, value); }
}
+ [Bindable(true)]
+ [Category("Behavior")]
+ [DefaultValue(DefaultInterval)]
public double Interval
{
get { return (double)GetValue(IntervalProperty); }
@@ -156,19 +189,24 @@ public double Interval
///
/// Gets or sets a value indicating whether the text can be changed by the use of the up or down buttons only.
///
- [Category("Common")]
public bool IsReadOnly
{
get { return (bool)GetValue(IsReadOnlyProperty); }
set { SetValue(IsReadOnlyProperty, value); }
}
+ [Bindable(true)]
+ [Category("Behavior")]
+ [DefaultValue(double.MaxValue)]
public double Maximum
{
get { return (double)GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
}
+ [Bindable(true)]
+ [Category("Behavior")]
+ [DefaultValue(double.MinValue)]
public double Minimum
{
get { return (double)GetValue(MinimumProperty); }
@@ -176,11 +214,12 @@ public double Minimum
}
///
- /// Gets or sets a value indicating whether the value to be added to or subtracted from remains always
- /// or it will change to and increase this.
+ /// Gets or sets a value indicating whether the value to be added to or subtracted from remains
+ /// always
+ /// or if it will increase faster after pressing the up/down button/arrow some time.
///
- [DefaultValue(true)]
[Category("Common")]
+ [DefaultValue(true)]
public bool Speedup
{
get { return (bool)GetValue(SpeedupProperty); }
@@ -188,7 +227,7 @@ public bool Speedup
}
///
- /// Gets or sets the formatting for the displaying
+ /// Gets or sets the formatting for the displaying
///
///
///
@@ -203,6 +242,7 @@ public string StringFormat
///
/// Gets or sets the horizontal alignment of the contents of the text box.
///
+ [Bindable(true)]
[Category("Common")]
[DefaultValue(TextAlignment.Right)]
public TextAlignment TextAlignment
@@ -211,6 +251,7 @@ public TextAlignment TextAlignment
set { SetValue(TextAlignmentProperty, value); }
}
+ [Bindable(true)]
[Category("Common")]
[DefaultValue(null)]
public double? Value
@@ -237,7 +278,9 @@ public override void OnApplyTemplate()
_valueTextBox = GetTemplateChild(ElementTextBox) as TextBox;
- if (_repeatUp == null || _repeatDown == null || _valueTextBox == null)
+ if (_repeatUp == null ||
+ _repeatDown == null ||
+ _valueTextBox == null)
{
throw new InvalidOperationException(string.Format("You have missed to specify {0}, {1} or {2} in your template", ElementNumericUp, ElementNumericDown, ElementTextBox));
}
@@ -313,7 +356,8 @@ protected void OnPreviewTextInput(object sender, TextCompositionEventArgs e)
const StringComparison strComp = StringComparison.InvariantCultureIgnoreCase;
e.Handled = true;
- if (string.IsNullOrWhiteSpace(e.Text) || e.Text.Length != 1)
+ if (string.IsNullOrWhiteSpace(e.Text) ||
+ e.Text.Length != 1)
{
return;
}
@@ -339,15 +383,16 @@ protected void OnPreviewTextInput(object sender, TextCompositionEventArgs e)
}
else
{
- if (numberFormatInfo.NegativeSign == text || text == numberFormatInfo.PositiveSign)
+ if (numberFormatInfo.NegativeSign == text ||
+ text == numberFormatInfo.PositiveSign)
{
if (textBox.SelectionStart == 0)
{
//check if text already has a + or - sign
if (textBox.Text.Length > 1)
{
- if (!textBox.Text.StartsWith(numberFormatInfo.NegativeSign, strComp)
- && !textBox.Text.StartsWith(numberFormatInfo.PositiveSign, strComp))
+ if (!textBox.Text.StartsWith(numberFormatInfo.NegativeSign, strComp) &&
+ !textBox.Text.StartsWith(numberFormatInfo.PositiveSign, strComp))
{
e.Handled = false;
}
@@ -366,9 +411,9 @@ protected void OnPreviewTextInput(object sender, TextCompositionEventArgs e)
}
}
}
- else if (text.Equals(scientificNotationChar, strComp)
- && !textBox.Text.Any(i => i.ToString(equivalentCulture).Equals(scientificNotationChar, strComp))
- && StringFormat.ToUpperInvariant().Contains(scientificNotationChar))
+ else if (text.Equals(scientificNotationChar, strComp) &&
+ textBox.SelectionStart > 0 &&
+ !textBox.Text.Any(i => i.ToString(equivalentCulture).Equals(scientificNotationChar, strComp)))
{
e.Handled = false;
}
@@ -378,51 +423,34 @@ protected void OnPreviewTextInput(object sender, TextCompositionEventArgs e)
protected virtual void OnSpeedupChanged(bool oldSpeedup, bool newSpeedup) {}
- private void EnableDisableUpDown()
- {
- EnableDisableUp();
- EnableDisableDown();
- }
-
- private void EnableDisableUp()
- {
- if (_repeatUp != null)
- {
- _repeatUp.IsEnabled = Value < Maximum;
- }
- }
-
- private void EnableDisableDown()
- {
- if (_repeatDown != null)
- {
- _repeatDown.IsEnabled = Value > Minimum;
- }
- }
-
///
- /// Raises the routed event.
+ /// Raises the routed event.
///
///
- /// Old value of the property
+ /// Old value of the property
///
///
- /// New value of the property
+ /// New value of the property
///
protected virtual void OnValueChanged(double? oldValue, double? newValue)
{
- if (!newValue.HasValue && _valueTextBox != null)
+ if (!newValue.HasValue)
{
- _valueTextBox.Text = null;
+ if (_valueTextBox != null)
+ {
+ _valueTextBox.Text = null;
+ }
return;
}
- if (_repeatUp != null && !_repeatUp.IsEnabled)
+ if (_repeatUp != null &&
+ !_repeatUp.IsEnabled)
{
_repeatUp.IsEnabled = true;
}
- if (_repeatDown != null && !_repeatDown.IsEnabled)
+ if (_repeatDown != null &&
+ !_repeatDown.IsEnabled)
{
_repeatDown.IsEnabled = true;
}
@@ -463,10 +491,14 @@ protected virtual void OnValueChanged(double? oldValue, double? newValue)
{
_valueTextBox.Text = newValue.Value.ToString(culture);
}
- else
+ else if (!StringFormat.Contains("{")) //then we may have a StringFormat of e.g. "N0"
{
_valueTextBox.Text = newValue.Value.ToString(StringFormat, culture);
}
+ else
+ {
+ _valueTextBox.Text = string.Format(culture, StringFormat, newValue.Value);
+ }
if ((bool)GetValue(TextboxHelper.IsMonitoringProperty))
{
@@ -485,6 +517,11 @@ private static object CoerceMaximum(DependencyObject d, object value)
return val < minimum ? minimum : val;
}
+ private static object CoerceStringFormat(DependencyObject d, object basevalue)
+ {
+ return basevalue ?? string.Empty;
+ }
+
private static object CoerceValue(DependencyObject d, object value)
{
if (value == null)
@@ -551,7 +588,8 @@ private static void OnStringFormatChanged(DependencyObject d, DependencyProperty
{
NumericUpDown nud = (NumericUpDown)d;
- if (nud._valueTextBox != null && nud.Value.HasValue)
+ if (nud._valueTextBox != null &&
+ nud.Value.HasValue)
{
nud._valueTextBox.Text = nud.Value.Value.ToString((string)e.NewValue);
}
@@ -573,12 +611,6 @@ private void ChangeValue(bool toPositive)
{
RaiseEvent(new RoutedEventArgs(toPositive ? IncrementValueEvent : DecrementValueEvent));
- if (!Value.HasValue)
- {
- Value = 0;
- return;
- }
-
if (Speedup)
{
double d = Interval * _internalLargeChange;
@@ -591,12 +623,36 @@ private void ChangeValue(bool toPositive)
if (toPositive)
{
- Value = Value + _internalIntervalMultiplierForCalculation;
+ Value = Value.GetValueOrDefault() + _internalIntervalMultiplierForCalculation;
}
else
{
- Value = Value - _internalIntervalMultiplierForCalculation;
+ Value = Value.GetValueOrDefault() - _internalIntervalMultiplierForCalculation;
}
+
+ _valueTextBox.CaretIndex = _valueTextBox.Text.Length;
+ }
+
+ private void EnableDisableDown()
+ {
+ if (_repeatDown != null)
+ {
+ _repeatDown.IsEnabled = Value > Minimum;
+ }
+ }
+
+ private void EnableDisableUp()
+ {
+ if (_repeatUp != null)
+ {
+ _repeatUp.IsEnabled = Value < Maximum;
+ }
+ }
+
+ private void EnableDisableUpDown()
+ {
+ EnableDisableUp();
+ EnableDisableDown();
}
private void OnGetFocus(object sender, RoutedEventArgs e)
diff --git a/MahApps.Metro/Themes/NumericUpDown.xaml b/MahApps.Metro/Themes/NumericUpDown.xaml
index e1c134a313..97bcc3cbfa 100644
--- a/MahApps.Metro/Themes/NumericUpDown.xaml
+++ b/MahApps.Metro/Themes/NumericUpDown.xaml
@@ -9,12 +9,22 @@