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 978188d891..caf07fbb36 100644
--- a/src/MahApps.Metro.Samples/MahApps.Metro.Demo/ExampleViews/TextExamples.xaml
+++ b/src/MahApps.Metro.Samples/MahApps.Metro.Demo/ExampleViews/TextExamples.xaml
@@ -403,6 +403,29 @@
IsReadOnly="{Binding ElementName=ReadOnlyCheck, Path=IsChecked, Mode=TwoWay}"
NumericInputMode="{Binding ElementName=NumericInputCheckBox, Path=SelectedItem, Mode=TwoWay}"
Value="500" />
+
+
+
+
+
+
/// Represents a Windows spin box (also known as an up-down control) that displays numeric values.
///
- [TemplatePart(Name = ElementNumericUp, Type = typeof(RepeatButton))]
- [TemplatePart(Name = ElementNumericDown, Type = typeof(RepeatButton))]
- [TemplatePart(Name = ElementTextBox, Type = typeof(TextBox))]
+ [TemplatePart(Name = PART_NumericUp, Type = typeof(RepeatButton))]
+ [TemplatePart(Name = PART_NumericDown, Type = typeof(RepeatButton))]
+ [TemplatePart(Name = PART_TextBox, Type = typeof(TextBox))]
public class NumericUpDown : Control
{
public static readonly RoutedEvent ValueIncrementedEvent = EventManager.RegisterRoutedEvent("ValueIncremented", RoutingStrategy.Bubble, typeof(NumericUpDownChangedRoutedEventHandler), typeof(NumericUpDown));
@@ -25,7 +25,7 @@ public class NumericUpDown : Control
public static readonly RoutedEvent MaximumReachedEvent = EventManager.RegisterRoutedEvent("MaximumReached", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(NumericUpDown));
public static readonly RoutedEvent MinimumReachedEvent = EventManager.RegisterRoutedEvent("MinimumReached", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(NumericUpDown));
public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler), typeof(NumericUpDown));
-
+
public static readonly DependencyProperty DelayProperty = DependencyProperty.Register(
"Delay",
typeof(int),
@@ -64,10 +64,10 @@ public class NumericUpDown : Control
new FrameworkPropertyMetadata(default(double?), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnValueChanged, CoerceValue));
public static readonly DependencyProperty ButtonsAlignmentProperty = DependencyProperty.Register(
- "ButtonsAlignment",
- typeof(ButtonsAlignment),
- typeof(NumericUpDown),
- new FrameworkPropertyMetadata(ButtonsAlignment.Right, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure));
+ "ButtonsAlignment",
+ typeof(ButtonsAlignment),
+ typeof(NumericUpDown),
+ new FrameworkPropertyMetadata(ButtonsAlignment.Right, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure));
public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register(
"Minimum",
@@ -88,15 +88,15 @@ public class NumericUpDown : Control
new FrameworkPropertyMetadata(DefaultInterval, IntervalChanged));
public static readonly DependencyProperty InterceptMouseWheelProperty = DependencyProperty.Register(
- "InterceptMouseWheel",
- typeof(bool),
- typeof(NumericUpDown),
+ "InterceptMouseWheel",
+ typeof(bool),
+ typeof(NumericUpDown),
new FrameworkPropertyMetadata(true));
public static readonly DependencyProperty TrackMouseWheelWhenMouseOverProperty = DependencyProperty.Register(
- "TrackMouseWheelWhenMouseOver",
- typeof(bool),
- typeof(NumericUpDown),
+ "TrackMouseWheelWhenMouseOver",
+ typeof(bool),
+ typeof(NumericUpDown),
new FrameworkPropertyMetadata(default(bool)));
public static readonly DependencyProperty HideUpDownButtonsProperty = DependencyProperty.Register(
@@ -111,23 +111,36 @@ public class NumericUpDown : Control
typeof(NumericUpDown),
new PropertyMetadata(20d));
+ public static readonly DependencyProperty UpDownButtonsFocusableProperty = DependencyProperty.Register(
+ "UpDownButtonsFocusable",
+ typeof(bool),
+ typeof(NumericUpDown),
+ new PropertyMetadata(true));
+
public static readonly DependencyProperty InterceptManualEnterProperty = DependencyProperty.Register(
"InterceptManualEnter",
typeof(bool),
typeof(NumericUpDown),
new PropertyMetadata(true, InterceptManualEnterChangedCallback));
+ public static readonly DependencyProperty ChangeValueOnTextChangedProperty = DependencyProperty.Register(
+ "ChangeValueOnTextChanged",
+ typeof(bool),
+ typeof(NumericUpDown),
+ new PropertyMetadata(true));
+
public static readonly DependencyProperty CultureProperty = DependencyProperty.Register(
"Culture",
typeof(CultureInfo),
typeof(NumericUpDown),
- new PropertyMetadata(null, (o, e) => {
- if (e.NewValue != e.OldValue)
- {
- var numUpDown = (NumericUpDown) o;
- numUpDown.OnValueChanged(numUpDown.Value, numUpDown.Value);
- }
- }));
+ new PropertyMetadata(null, (o, e) =>
+ {
+ if (e.NewValue != e.OldValue)
+ {
+ var numUpDown = (NumericUpDown)o;
+ numUpDown.OnValueChanged(numUpDown.Value, numUpDown.Value);
+ }
+ }));
public static readonly DependencyProperty NumericInputModeProperty = DependencyProperty.Register(
"NumericInputMode",
@@ -142,7 +155,7 @@ public class NumericUpDown : Control
new PropertyMetadata(default(bool), OnSnapToMultipleOfIntervalChanged));
public static readonly DependencyProperty ParsingNumberStyleProperty = DependencyProperty.Register(
- "ParsingNumberStyle",
+ "ParsingNumberStyle",
typeof(NumberStyles),
typeof(NumericUpDown),
new PropertyMetadata(NumberStyles.Any));
@@ -180,19 +193,20 @@ private static void InterceptManualEnterChangedCallback(DependencyObject depende
private const double DefaultInterval = 1d;
private const int DefaultDelay = 500;
- private const string ElementNumericDown = "PART_NumericDown";
- private const string ElementNumericUp = "PART_NumericUp";
- private const string ElementTextBox = "PART_TextBox";
-
- private Lazy _handlesMouseWheelScrolling = new Lazy();
- private double _internalIntervalMultiplierForCalculation = DefaultInterval;
- private double _internalLargeChange = DefaultInterval * 100;
- private double _intervalValueSinceReset;
- private bool _manualChange;
- private RepeatButton _repeatDown;
- private RepeatButton _repeatUp;
- private TextBox _valueTextBox;
- private ScrollViewer _scrollViewer;
+ private const string PART_NumericDown = "PART_NumericDown";
+ private const string PART_NumericUp = "PART_NumericUp";
+ private const string PART_TextBox = "PART_TextBox";
+ private const string PART_ContentHost = "PART_ContentHost";
+
+ private Lazy handlesMouseWheelScrolling = new Lazy();
+ private double internalIntervalMultiplierForCalculation = DefaultInterval;
+ private double internalLargeChange = DefaultInterval * 100;
+ private double intervalValueSinceReset;
+ private bool manualChange;
+ private RepeatButton repeatDown;
+ private RepeatButton repeatUp;
+ private TextBox valueTextBox;
+ private ScrollViewer scrollViewer;
static NumericUpDown()
{
@@ -201,13 +215,13 @@ static NumericUpDown()
VerticalContentAlignmentProperty.OverrideMetadata(typeof(NumericUpDown), new FrameworkPropertyMetadata(VerticalAlignment.Center));
HorizontalContentAlignmentProperty.OverrideMetadata(typeof(NumericUpDown), new FrameworkPropertyMetadata(HorizontalAlignment.Right));
- EventManager.RegisterClassHandler(typeof(NumericUpDown), UIElement.GotFocusEvent, new RoutedEventHandler(OnGotFocus));
+ EventManager.RegisterClassHandler(typeof(NumericUpDown), GotFocusEvent, new RoutedEventHandler(OnGotFocus));
}
public event RoutedPropertyChangedEventHandler ValueChanged
{
- add { AddHandler(ValueChangedEvent, value); }
- remove { RemoveHandler(ValueChangedEvent, value); }
+ add { this.AddHandler(ValueChangedEvent, value); }
+ remove { this.RemoveHandler(ValueChangedEvent, value); }
}
///
@@ -215,8 +229,8 @@ static NumericUpDown()
///
public event RoutedEventHandler MaximumReached
{
- add { AddHandler(MaximumReachedEvent, value); }
- remove { RemoveHandler(MaximumReachedEvent, value); }
+ add { this.AddHandler(MaximumReachedEvent, value); }
+ remove { this.RemoveHandler(MaximumReachedEvent, value); }
}
///
@@ -224,26 +238,26 @@ static NumericUpDown()
///
public event RoutedEventHandler MinimumReached
{
- add { AddHandler(MinimumReachedEvent, value); }
- remove { RemoveHandler(MinimumReachedEvent, value); }
+ add { this.AddHandler(MinimumReachedEvent, value); }
+ remove { this.RemoveHandler(MinimumReachedEvent, value); }
}
public event NumericUpDownChangedRoutedEventHandler ValueIncremented
{
- add { AddHandler(ValueIncrementedEvent, value); }
- remove { RemoveHandler(ValueIncrementedEvent, value); }
+ add { this.AddHandler(ValueIncrementedEvent, value); }
+ remove { this.RemoveHandler(ValueIncrementedEvent, value); }
}
public event NumericUpDownChangedRoutedEventHandler ValueDecremented
{
- add { AddHandler(ValueDecrementedEvent, value); }
- remove { RemoveHandler(ValueDecrementedEvent, value); }
+ add { this.AddHandler(ValueDecrementedEvent, value); }
+ remove { this.RemoveHandler(ValueDecrementedEvent, value); }
}
public event RoutedEventHandler DelayChanged
{
- add { AddHandler(DelayChangedEvent, value); }
- remove { RemoveHandler(DelayChangedEvent, value); }
+ add { this.AddHandler(DelayChangedEvent, value); }
+ remove { this.RemoveHandler(DelayChangedEvent, value); }
}
///
@@ -257,8 +271,8 @@ static NumericUpDown()
[Category("Behavior")]
public int Delay
{
- get { return (int)GetValue(DelayProperty); }
- set { SetValue(DelayProperty, value); }
+ get { return (int)this.GetValue(DelayProperty); }
+ set { this.SetValue(DelayProperty, value); }
}
///
@@ -269,8 +283,8 @@ public int Delay
[DefaultValue(true)]
public bool InterceptArrowKeys
{
- get { return (bool)GetValue(InterceptArrowKeysProperty); }
- set { SetValue(InterceptArrowKeysProperty, value); }
+ get { return (bool)this.GetValue(InterceptArrowKeysProperty); }
+ set { this.SetValue(InterceptArrowKeysProperty, value); }
}
///
@@ -280,8 +294,8 @@ public bool InterceptArrowKeys
[DefaultValue(true)]
public bool InterceptMouseWheel
{
- get { return (bool)GetValue(InterceptMouseWheelProperty); }
- set { SetValue(InterceptMouseWheelProperty, value); }
+ get { return (bool)this.GetValue(InterceptMouseWheelProperty); }
+ set { this.SetValue(InterceptMouseWheelProperty, value); }
}
///
@@ -294,8 +308,8 @@ public bool InterceptMouseWheel
[DefaultValue(false)]
public bool TrackMouseWheelWhenMouseOver
{
- get { return (bool)GetValue(TrackMouseWheelWhenMouseOverProperty); }
- set { SetValue(TrackMouseWheelWhenMouseOverProperty, value); }
+ get { return (bool)this.GetValue(TrackMouseWheelWhenMouseOverProperty); }
+ set { this.SetValue(TrackMouseWheelWhenMouseOverProperty, value); }
}
///
@@ -305,8 +319,18 @@ public bool TrackMouseWheelWhenMouseOver
[DefaultValue(true)]
public bool InterceptManualEnter
{
- get { return (bool)GetValue(InterceptManualEnterProperty); }
- set { SetValue(InterceptManualEnterProperty, value); }
+ get { return (bool)this.GetValue(InterceptManualEnterProperty); }
+ set { this.SetValue(InterceptManualEnterProperty, value); }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether the value will be changed directly on every TextBox text changed event or when using the Enter key.
+ ///
+ [Category("Behavior")]
+ public bool ChangeValueOnTextChanged
+ {
+ get { return (bool)this.GetValue(ChangeValueOnTextChangedProperty); }
+ set { this.SetValue(ChangeValueOnTextChangedProperty, value); }
}
///
@@ -316,8 +340,8 @@ public bool InterceptManualEnter
[DefaultValue(null)]
public CultureInfo Culture
{
- get { return (CultureInfo)GetValue(CultureProperty); }
- set { SetValue(CultureProperty, value); }
+ get { return (CultureInfo)this.GetValue(CultureProperty); }
+ set { this.SetValue(CultureProperty, value); }
}
///
@@ -342,8 +366,8 @@ public CultureInfo Culture
[DefaultValue(false)]
public bool HideUpDownButtons
{
- get { return (bool)GetValue(HideUpDownButtonsProperty); }
- set { SetValue(HideUpDownButtonsProperty, value); }
+ get { return (bool)this.GetValue(HideUpDownButtonsProperty); }
+ set { this.SetValue(HideUpDownButtonsProperty, value); }
}
[Bindable(true)]
@@ -351,17 +375,29 @@ public bool HideUpDownButtons
[DefaultValue(20d)]
public double UpDownButtonsWidth
{
- get { return (double)GetValue(UpDownButtonsWidthProperty); }
- set { SetValue(UpDownButtonsWidthProperty, value); }
+ get { return (double)this.GetValue(UpDownButtonsWidthProperty); }
+ set { this.SetValue(UpDownButtonsWidthProperty, value); }
+ }
+
+ ///
+ /// Gets or sets whether the up and down buttons will got the focus when using them.
+ ///
+ [Bindable(true)]
+ [Category("Behavior")]
+ [DefaultValue(true)]
+ public bool UpDownButtonsFocusable
+ {
+ get { return (bool)this.GetValue(UpDownButtonsFocusableProperty); }
+ set { this.SetValue(UpDownButtonsFocusableProperty, value); }
}
[Bindable(true)]
[Category("Appearance")]
[DefaultValue(ButtonsAlignment.Right)]
- public Controls.ButtonsAlignment ButtonsAlignment
+ public ButtonsAlignment ButtonsAlignment
{
- get { return (ButtonsAlignment)GetValue(ButtonsAlignmentProperty); }
- set { SetValue(ButtonsAlignmentProperty, value); }
+ get { return (ButtonsAlignment)this.GetValue(ButtonsAlignmentProperty); }
+ set { this.SetValue(ButtonsAlignmentProperty, value); }
}
[Bindable(true)]
@@ -369,8 +405,8 @@ public Controls.ButtonsAlignment ButtonsAlignment
[DefaultValue(DefaultInterval)]
public double Interval
{
- get { return (double)GetValue(IntervalProperty); }
- set { SetValue(IntervalProperty, value); }
+ get { return (double)this.GetValue(IntervalProperty); }
+ set { this.SetValue(IntervalProperty, value); }
}
///
@@ -381,8 +417,8 @@ public double Interval
[DefaultValue(false)]
public bool IsReadOnly
{
- get { return (bool)GetValue(IsReadOnlyProperty); }
- set { SetValue(IsReadOnlyProperty, value); }
+ get { return (bool)this.GetValue(IsReadOnlyProperty); }
+ set { this.SetValue(IsReadOnlyProperty, value); }
}
[Bindable(true)]
@@ -390,8 +426,8 @@ public bool IsReadOnly
[DefaultValue(double.MaxValue)]
public double Maximum
{
- get { return (double)GetValue(MaximumProperty); }
- set { SetValue(MaximumProperty, value); }
+ get { return (double)this.GetValue(MaximumProperty); }
+ set { this.SetValue(MaximumProperty, value); }
}
[Bindable(true)]
@@ -399,8 +435,8 @@ public double Maximum
[DefaultValue(double.MinValue)]
public double Minimum
{
- get { return (double)GetValue(MinimumProperty); }
- set { SetValue(MinimumProperty, value); }
+ get { return (double)this.GetValue(MinimumProperty); }
+ set { this.SetValue(MinimumProperty, value); }
}
///
@@ -412,8 +448,8 @@ public double Minimum
[DefaultValue(true)]
public bool Speedup
{
- get { return (bool)GetValue(SpeedupProperty); }
- set { SetValue(SpeedupProperty, value); }
+ get { return (bool)this.GetValue(SpeedupProperty); }
+ set { this.SetValue(SpeedupProperty, value); }
}
///
@@ -425,8 +461,8 @@ public bool Speedup
[Category("Common")]
public string StringFormat
{
- get { return (string)GetValue(StringFormatProperty); }
- set { SetValue(StringFormatProperty, value); }
+ get { return (string)this.GetValue(StringFormatProperty); }
+ set { this.SetValue(StringFormatProperty, value); }
}
///
@@ -437,8 +473,8 @@ public string StringFormat
[DefaultValue(TextAlignment.Right)]
public TextAlignment TextAlignment
{
- get { return (TextAlignment)GetValue(TextAlignmentProperty); }
- set { SetValue(TextAlignmentProperty, value); }
+ get { return (TextAlignment)this.GetValue(TextAlignmentProperty); }
+ set { this.SetValue(TextAlignmentProperty, value); }
}
[Bindable(true)]
@@ -446,13 +482,13 @@ public TextAlignment TextAlignment
[DefaultValue(null)]
public double? Value
{
- get { return (double?)GetValue(ValueProperty); }
- set { SetValue(ValueProperty, value); }
+ get { return (double?)this.GetValue(ValueProperty); }
+ set { this.SetValue(ValueProperty, value); }
}
private CultureInfo SpecificCultureInfo
{
- get { return Culture ?? Language.GetSpecificCulture(); }
+ get { return this.Culture ?? this.Language.GetSpecificCulture(); }
}
///
@@ -462,8 +498,8 @@ private CultureInfo SpecificCultureInfo
[DefaultValue(NumericInput.All)]
public NumericInput NumericInputMode
{
- get { return (NumericInput)GetValue(NumericInputModeProperty); }
- set { SetValue(NumericInputModeProperty, value); }
+ get { return (NumericInput)this.GetValue(NumericInputModeProperty); }
+ set { this.SetValue(NumericInputModeProperty, value); }
}
///
@@ -474,8 +510,8 @@ public NumericInput NumericInputMode
[DefaultValue(false)]
public bool SnapToMultipleOfInterval
{
- get { return (bool)GetValue(SnapToMultipleOfIntervalProperty); }
- set { SetValue(SnapToMultipleOfIntervalProperty, value); }
+ get { return (bool)this.GetValue(SnapToMultipleOfIntervalProperty); }
+ set { this.SetValue(SnapToMultipleOfIntervalProperty, value); }
}
///
@@ -485,8 +521,8 @@ public bool SnapToMultipleOfInterval
[DefaultValue(NumberStyles.Any)]
public NumberStyles ParsingNumberStyle
{
- get { return (NumberStyles)GetValue(ParsingNumberStyleProperty); }
- set { SetValue(ParsingNumberStyleProperty, value); }
+ get { return (NumberStyles)this.GetValue(ParsingNumberStyleProperty); }
+ set { this.SetValue(ParsingNumberStyleProperty, value); }
}
///
@@ -496,8 +532,8 @@ public NumberStyles ParsingNumberStyle
[DefaultValue(false)]
public bool SwitchUpDownButtons
{
- get { return (bool)GetValue(SwitchUpDownButtonsProperty); }
- set { SetValue(SwitchUpDownButtonsProperty, value); }
+ get { return (bool)this.GetValue(SwitchUpDownButtonsProperty); }
+ set { this.SetValue(SwitchUpDownButtonsProperty, value); }
}
///
@@ -539,61 +575,77 @@ public override void OnApplyTemplate()
{
base.OnApplyTemplate();
- _repeatUp = GetTemplateChild(ElementNumericUp) as RepeatButton;
- _repeatDown = GetTemplateChild(ElementNumericDown) as RepeatButton;
-
- _valueTextBox = GetTemplateChild(ElementTextBox) as TextBox;
+ this.repeatUp = this.GetTemplateChild(PART_NumericUp) as RepeatButton;
+ this.repeatDown = this.GetTemplateChild(PART_NumericDown) as RepeatButton;
- if (_repeatUp == null ||
- _repeatDown == null ||
- _valueTextBox == null)
+ this.valueTextBox = this.GetTemplateChild(PART_TextBox) as TextBox;
+
+ if (this.repeatUp == null || this.repeatDown == null || this.valueTextBox == null)
{
- throw new InvalidOperationException(string.Format("You have missed to specify {0}, {1} or {2} in your template", ElementNumericUp, ElementNumericDown, ElementTextBox));
+ throw new InvalidOperationException($"You have missed to specify {PART_NumericUp}, {PART_NumericDown} or {PART_TextBox} in your template!");
}
this.ToggleReadOnlyMode(this.IsReadOnly | !this.InterceptManualEnter);
- _repeatUp.Click += (o, e) => ChangeValueWithSpeedUp(true);
- _repeatDown.Click += (o, e) => ChangeValueWithSpeedUp(false);
+ this.repeatUp.Click += (o, e) =>
+ {
+ this.ChangeValueWithSpeedUp(true);
- _repeatUp.PreviewMouseUp += (o, e) => ResetInternal();
- _repeatDown.PreviewMouseUp += (o, e) => ResetInternal();
-
- OnValueChanged(Value, Value);
+ if (!this.UpDownButtonsFocusable)
+ {
+ this.manualChange = false;
+ this.InternalSetText(this.Value);
+ }
+ };
+ this.repeatDown.Click += (o, e) =>
+ {
+ this.ChangeValueWithSpeedUp(false);
+
+ if (!this.UpDownButtonsFocusable)
+ {
+ this.manualChange = false;
+ this.InternalSetText(this.Value);
+ }
+ };
- _scrollViewer = TryFindScrollViewer();
+ this.repeatUp.PreviewMouseUp += (o, e) => this.ResetInternal();
+ this.repeatDown.PreviewMouseUp += (o, e) => this.ResetInternal();
+
+ this.OnValueChanged(this.Value, this.Value);
+
+ this.scrollViewer = this.TryFindScrollViewer();
}
private void ToggleReadOnlyMode(bool isReadOnly)
{
- if (_repeatUp == null || _repeatDown == null || _valueTextBox == null)
+ if (this.repeatUp == null || this.repeatDown == null || this.valueTextBox == null)
{
return;
}
-
+
if (isReadOnly)
{
- _valueTextBox.LostFocus -= OnTextBoxLostFocus;
- _valueTextBox.PreviewTextInput -= OnPreviewTextInput;
- _valueTextBox.PreviewKeyDown -= OnTextBoxKeyDown;
- _valueTextBox.TextChanged -= OnTextChanged;
- DataObject.RemovePastingHandler(_valueTextBox, OnValueTextBoxPaste);
+ this.valueTextBox.LostFocus -= this.OnTextBoxLostFocus;
+ this.valueTextBox.PreviewTextInput -= this.OnPreviewTextInput;
+ this.valueTextBox.PreviewKeyDown -= this.OnTextBoxKeyDown;
+ this.valueTextBox.TextChanged -= this.OnTextChanged;
+ DataObject.RemovePastingHandler(this.valueTextBox, this.OnValueTextBoxPaste);
}
else
{
- _valueTextBox.LostFocus += OnTextBoxLostFocus;
- _valueTextBox.PreviewTextInput += OnPreviewTextInput;
- _valueTextBox.PreviewKeyDown += OnTextBoxKeyDown;
- _valueTextBox.TextChanged += OnTextChanged;
- DataObject.AddPastingHandler(_valueTextBox, OnValueTextBoxPaste);
+ this.valueTextBox.LostFocus += this.OnTextBoxLostFocus;
+ this.valueTextBox.PreviewTextInput += this.OnPreviewTextInput;
+ this.valueTextBox.PreviewKeyDown += this.OnTextBoxKeyDown;
+ this.valueTextBox.TextChanged += this.OnTextChanged;
+ DataObject.AddPastingHandler(this.valueTextBox, this.OnValueTextBoxPaste);
}
}
public void SelectAll()
{
- if (_valueTextBox != null)
+ if (this.valueTextBox != null)
{
- _valueTextBox.SelectAll();
+ this.valueTextBox.SelectAll();
}
}
@@ -601,14 +653,14 @@ protected virtual void OnDelayChanged(int oldDelay, int newDelay)
{
if (oldDelay != newDelay)
{
- if (_repeatDown != null)
+ if (this.repeatDown != null)
{
- _repeatDown.Delay = newDelay;
+ this.repeatDown.Delay = newDelay;
}
- if (_repeatUp != null)
+ if (this.repeatUp != null)
{
- _repeatUp.Delay = newDelay;
+ this.repeatUp.Delay = newDelay;
}
}
}
@@ -625,27 +677,34 @@ protected override void OnPreviewKeyDown(KeyEventArgs e)
{
base.OnPreviewKeyDown(e);
- if (!InterceptArrowKeys)
+ if (!this.InterceptArrowKeys)
{
return;
}
switch (e.Key)
{
+ case Key.Enter:
+ if (!this.ChangeValueOnTextChanged)
+ {
+ this.ChangeValueFromTextInput(e.OriginalSource as TextBox);
+ }
+
+ break;
case Key.Up:
- ChangeValueWithSpeedUp(true);
+ this.ChangeValueWithSpeedUp(true);
e.Handled = true;
break;
case Key.Down:
- ChangeValueWithSpeedUp(false);
+ this.ChangeValueWithSpeedUp(false);
e.Handled = true;
break;
}
if (e.Handled)
{
- _manualChange = false;
- InternalSetText(Value);
+ this.manualChange = false;
+ this.InternalSetText(this.Value);
}
}
@@ -656,7 +715,7 @@ protected override void OnPreviewKeyUp(KeyEventArgs e)
if (e.Key == Key.Down ||
e.Key == Key.Up)
{
- ResetInternal();
+ this.ResetInternal();
}
}
@@ -664,37 +723,37 @@ protected override void OnPreviewMouseWheel(MouseWheelEventArgs e)
{
base.OnPreviewMouseWheel(e);
- if (InterceptMouseWheel && (IsFocused || _valueTextBox.IsFocused || TrackMouseWheelWhenMouseOver))
+ if (this.InterceptMouseWheel && (this.IsFocused || this.valueTextBox.IsFocused || this.TrackMouseWheelWhenMouseOver))
{
bool increment = e.Delta > 0;
- _manualChange = false;
- ChangeValueInternal(increment);
+ this.manualChange = false;
+ this.ChangeValueInternal(increment);
}
- if (_scrollViewer != null && _handlesMouseWheelScrolling.Value != null)
+ if (this.scrollViewer != null && this.handlesMouseWheelScrolling.Value != null)
{
- if (TrackMouseWheelWhenMouseOver)
+ if (this.TrackMouseWheelWhenMouseOver)
{
- _handlesMouseWheelScrolling.Value.SetValue(_scrollViewer, true, null);
+ this.handlesMouseWheelScrolling.Value.SetValue(this.scrollViewer, true, null);
}
- else if (InterceptMouseWheel)
+ else if (this.InterceptMouseWheel)
{
- _handlesMouseWheelScrolling.Value.SetValue(_scrollViewer, _valueTextBox.IsFocused, null);
+ this.handlesMouseWheelScrolling.Value.SetValue(this.scrollViewer, this.valueTextBox.IsFocused, null);
}
else
{
- _handlesMouseWheelScrolling.Value.SetValue(_scrollViewer, true, null);
+ this.handlesMouseWheelScrolling.Value.SetValue(this.scrollViewer, true, null);
}
}
}
-
+
protected void OnPreviewTextInput(object sender, TextCompositionEventArgs e)
{
var textBox = ((TextBox)sender);
var fullText = textBox.Text.Remove(textBox.SelectionStart, textBox.SelectionLength).Insert(textBox.CaretIndex, e.Text);
double convertedValue;
- e.Handled = !ValidateText(fullText, out convertedValue);
- this._manualChange = true;
+ e.Handled = !this.ValidateText(fullText, out convertedValue);
+ this.manualChange = true;
}
protected virtual void OnSpeedupChanged(bool oldSpeedup, bool newSpeedup)
@@ -712,63 +771,65 @@ protected virtual void OnSpeedupChanged(bool oldSpeedup, bool newSpeedup)
///
protected virtual void OnValueChanged(double? oldValue, double? newValue)
{
- if (!_manualChange)
+ if (!this.manualChange)
{
if (!newValue.HasValue)
{
- if (_valueTextBox != null)
+ if (this.valueTextBox != null)
{
- _valueTextBox.Text = null;
+ this.valueTextBox.Text = null;
}
+
if (oldValue != newValue)
{
this.RaiseEvent(new RoutedPropertyChangedEventArgs(oldValue, newValue, ValueChangedEvent));
}
+
return;
}
- if (_repeatUp != null && !_repeatUp.IsEnabled)
+ if (this.repeatUp != null && !this.repeatUp.IsEnabled)
{
- _repeatUp.IsEnabled = true;
+ this.repeatUp.IsEnabled = true;
}
- if (_repeatDown != null && !_repeatDown.IsEnabled)
+ if (this.repeatDown != null && !this.repeatDown.IsEnabled)
{
- _repeatDown.IsEnabled = true;
+ this.repeatDown.IsEnabled = true;
}
- if (newValue <= Minimum)
+ if (newValue <= this.Minimum)
{
- if (_repeatDown != null)
+ if (this.repeatDown != null)
{
- _repeatDown.IsEnabled = false;
+ this.repeatDown.IsEnabled = false;
}
- ResetInternal();
+ this.ResetInternal();
- if (IsLoaded)
+ if (this.IsLoaded)
{
- RaiseEvent(new RoutedEventArgs(MinimumReachedEvent));
+ this.RaiseEvent(new RoutedEventArgs(MinimumReachedEvent));
}
}
- if (newValue >= Maximum)
+ if (newValue >= this.Maximum)
{
- if (_repeatUp != null)
+ if (this.repeatUp != null)
{
- _repeatUp.IsEnabled = false;
+ this.repeatUp.IsEnabled = false;
}
- ResetInternal();
- if (IsLoaded)
+ this.ResetInternal();
+ if (this.IsLoaded)
{
- RaiseEvent(new RoutedEventArgs(MaximumReachedEvent));
+ this.RaiseEvent(new RoutedEventArgs(MaximumReachedEvent));
}
}
- if (_valueTextBox != null)
+ if (this.valueTextBox != null)
{
- InternalSetText(newValue);
+ this.InternalSetText(newValue);
}
}
@@ -804,14 +865,17 @@ private static object CoerceValue(DependencyObject d, object value)
{
val = Math.Truncate(val);
}
+
if (val < numericUpDown.Minimum)
{
return numericUpDown.Minimum;
}
+
if (val > numericUpDown.Maximum)
{
return numericUpDown.Maximum;
}
+
return val;
}
@@ -860,7 +924,7 @@ 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.InternalSetText(nud.Value);
}
@@ -935,15 +999,15 @@ private void InternalSetText(double? newValue)
{
if (!newValue.HasValue)
{
- _valueTextBox.Text = null;
+ this.valueTextBox.Text = null;
return;
}
- _valueTextBox.Text = FormattedValue(newValue, StringFormat, SpecificCultureInfo);
+ this.valueTextBox.Text = this.FormattedValue(newValue, this.StringFormat, this.SpecificCultureInfo);
- if ((bool)GetValue(TextBoxHelper.IsMonitoringProperty))
+ if ((bool)this.GetValue(TextBoxHelper.IsMonitoringProperty))
{
- SetValue(TextBoxHelper.TextLengthProperty, _valueTextBox.Text.Length);
+ this.SetValue(TextBoxHelper.TextLengthProperty, this.valueTextBox.Text.Length);
}
}
@@ -960,6 +1024,7 @@ private string FormattedValue(double? newValue, string format, CultureInfo cultu
// HEX DOES SUPPORT INT ONLY.
return ((int)newValue.Value).ToString(match.Groups["simpleHEX"].Value, culture);
}
+
if (match.Groups["complexHEX"].Success)
{
return string.Format(culture, match.Groups["complexHEX"].Value, (int)newValue.Value);
@@ -983,6 +1048,7 @@ private string FormattedValue(double? newValue, string format, CultureInfo cultu
// then we may have a StringFormat of e.g. "N0"
return value.ToString(format, culture);
}
+
return string.Format(culture, format, value);
}
}
@@ -992,151 +1058,162 @@ private string FormattedValue(double? newValue, string format, CultureInfo cultu
private ScrollViewer TryFindScrollViewer()
{
- _valueTextBox.ApplyTemplate();
- var scrollViewer = _valueTextBox.Template.FindName("PART_ContentHost", _valueTextBox) as ScrollViewer;
- if (scrollViewer != null)
+ this.valueTextBox.ApplyTemplate();
+
+ var scrollViewerFromTemplate = this.valueTextBox.Template.FindName(PART_ContentHost, this.valueTextBox) as ScrollViewer;
+ if (scrollViewerFromTemplate != null)
{
- _handlesMouseWheelScrolling = new Lazy(() => _scrollViewer.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance).SingleOrDefault(i => i.Name == "HandlesMouseWheelScrolling"));
+ this.handlesMouseWheelScrolling = new Lazy(() => this.scrollViewer.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance).SingleOrDefault(i => i.Name == "HandlesMouseWheelScrolling"));
}
- return scrollViewer;
+
+ return scrollViewerFromTemplate;
}
private void ChangeValueWithSpeedUp(bool toPositive)
{
- if (IsReadOnly)
+ if (this.IsReadOnly)
{
return;
}
-
+
double direction = toPositive ? 1 : -1;
- if (Speedup)
+ if (this.Speedup)
{
- double d = Interval * _internalLargeChange;
- if ((_intervalValueSinceReset += Interval * _internalIntervalMultiplierForCalculation) > d)
+ double d = this.Interval * this.internalLargeChange;
+ if ((this.intervalValueSinceReset += this.Interval * this.internalIntervalMultiplierForCalculation) > d)
{
- _internalLargeChange *= 10;
- _internalIntervalMultiplierForCalculation *= 10;
+ this.internalLargeChange *= 10;
+ this.internalIntervalMultiplierForCalculation *= 10;
}
- ChangeValueInternal(direction * _internalIntervalMultiplierForCalculation);
+ this.ChangeValueInternal(direction * this.internalIntervalMultiplierForCalculation);
}
else
{
- ChangeValueInternal(direction * Interval);
+ this.ChangeValueInternal(direction * this.Interval);
}
}
private void ChangeValueInternal(bool addInterval)
{
- ChangeValueInternal(addInterval ? Interval : -Interval);
+ this.ChangeValueInternal(addInterval ? this.Interval : -this.Interval);
}
private void ChangeValueInternal(double interval)
{
- if (IsReadOnly)
+ if (this.IsReadOnly)
{
return;
}
-
- NumericUpDownChangedRoutedEventArgs routedEvent = interval > 0 ?
- new NumericUpDownChangedRoutedEventArgs(ValueIncrementedEvent, interval) :
- new NumericUpDownChangedRoutedEventArgs(ValueDecrementedEvent, interval);
- RaiseEvent(routedEvent);
+ NumericUpDownChangedRoutedEventArgs routedEvent = interval > 0 ? new NumericUpDownChangedRoutedEventArgs(ValueIncrementedEvent, interval) : new NumericUpDownChangedRoutedEventArgs(ValueDecrementedEvent, interval);
+
+ this.RaiseEvent(routedEvent);
if (!routedEvent.Handled)
{
- ChangeValueBy(routedEvent.Interval);
- _valueTextBox.CaretIndex = _valueTextBox.Text.Length;
+ this.ChangeValueBy(routedEvent.Interval);
+ this.valueTextBox.CaretIndex = this.valueTextBox.Text.Length;
}
}
private void ChangeValueBy(double difference)
{
- var newValue = Value.GetValueOrDefault() + difference;
- SetValueTo(newValue);
+ var newValue = this.Value.GetValueOrDefault() + difference;
+ this.SetValueTo(newValue);
}
private void SetValueTo(double newValue)
{
- if (SnapToMultipleOfInterval && Math.Abs(this.Interval) > 0)
+ var value = newValue;
+
+ if (this.SnapToMultipleOfInterval && Math.Abs(this.Interval) > 0)
{
- newValue = Math.Round(newValue / Interval) * Interval;
+ value = Math.Round(newValue / this.Interval) * this.Interval;
}
- if (newValue > Maximum)
+ if (value > this.Maximum)
{
- newValue = this.Maximum;
+ value = this.Maximum;
}
- else if (newValue < Minimum)
+ else if (value < this.Minimum)
{
- newValue = this.Minimum;
+ value = this.Minimum;
}
- SetCurrentValue(ValueProperty, CoerceValue(this, newValue));
+ this.SetCurrentValue(ValueProperty, CoerceValue(this, value));
}
private void EnableDisableDown()
{
- if (_repeatDown != null)
+ if (this.repeatDown != null)
{
- _repeatDown.IsEnabled = Value > Minimum;
+ this.repeatDown.IsEnabled = this.Value > this.Minimum;
}
}
private void EnableDisableUp()
{
- if (_repeatUp != null)
+ if (this.repeatUp != null)
{
- _repeatUp.IsEnabled = Value < Maximum;
+ this.repeatUp.IsEnabled = this.Value < this.Maximum;
}
}
private void EnableDisableUpDown()
{
- EnableDisableUp();
- EnableDisableDown();
+ this.EnableDisableUp();
+ this.EnableDisableDown();
}
private void OnTextBoxKeyDown(object sender, KeyEventArgs e)
{
- _manualChange = _manualChange || e.Key == Key.Back || e.Key == Key.Delete || e.Key == Key.Decimal || e.Key == Key.OemComma || e.Key == Key.OemPeriod;
+ this.manualChange = this.manualChange || e.Key == Key.Back || e.Key == Key.Delete || e.Key == Key.Decimal || e.Key == Key.OemComma || e.Key == Key.OemPeriod;
}
private void OnTextBoxLostFocus(object sender, RoutedEventArgs e)
{
- if (!InterceptManualEnter)
+ this.ChangeValueFromTextInput(sender as TextBox);
+ }
+
+ private void ChangeValueFromTextInput(TextBox textBox)
+ {
+ if (textBox is null || !this.InterceptManualEnter)
{
return;
}
- if (_manualChange)
+ if (this.manualChange)
{
- TextBox tb = (TextBox)sender;
- _manualChange = false;
+ this.manualChange = false;
double convertedValue;
- if (ValidateText(tb.Text, out convertedValue))
+ if (this.ValidateText(textBox.Text, out convertedValue))
{
- SetValueTo(convertedValue);
+ this.SetValueTo(convertedValue);
}
}
- OnValueChanged(Value, Value);
+ this.OnValueChanged(this.Value, this.Value);
}
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
+ if (!this.ChangeValueOnTextChanged)
+ {
+ return;
+ }
+
if (string.IsNullOrEmpty(((TextBox)sender).Text))
{
- Value = null;
+ this.Value = null;
}
- else if (_manualChange || e.UndoAction == UndoAction.Undo || e.UndoAction == UndoAction.Redo)
+ else if (this.manualChange || e.UndoAction == UndoAction.Undo || e.UndoAction == UndoAction.Redo)
{
double convertedValue;
- if (ValidateText(((TextBox)sender).Text, out convertedValue))
+ if (this.ValidateText(((TextBox)sender).Text, out convertedValue))
{
- SetCurrentValue(ValueProperty, convertedValue);
+ this.SetCurrentValue(ValueProperty, convertedValue);
}
}
}
@@ -1157,76 +1234,76 @@ private void OnValueTextBoxPaste(object sender, DataObjectPastingEventArgs e)
string newText = string.Concat(textPresent.Substring(0, textBox.SelectionStart), text, textPresent.Substring(textBox.SelectionStart + textBox.SelectionLength));
double convertedValue;
- if (!ValidateText(newText, out convertedValue))
+ if (!this.ValidateText(newText, out convertedValue))
{
e.CancelCommand();
}
else
{
- _manualChange = true;
+ this.manualChange = true;
}
}
private void RaiseChangeDelay()
{
- RaiseEvent(new RoutedEventArgs(DelayChangedEvent));
+ this.RaiseEvent(new RoutedEventArgs(DelayChangedEvent));
}
private void ResetInternal()
{
- if (IsReadOnly)
+ if (this.IsReadOnly)
{
return;
}
-
- _internalLargeChange = 100 * Interval;
- _internalIntervalMultiplierForCalculation = Interval;
- _intervalValueSinceReset = 0;
+
+ this.internalLargeChange = 100 * this.Interval;
+ this.internalIntervalMultiplierForCalculation = this.Interval;
+ this.intervalValueSinceReset = 0;
}
private bool ValidateText(string text, out double convertedValue)
{
convertedValue = 0d;
- if (text == SpecificCultureInfo.NumberFormat.PositiveSign
- || text == SpecificCultureInfo.NumberFormat.NegativeSign)
+ if (text == this.SpecificCultureInfo.NumberFormat.PositiveSign
+ || text == this.SpecificCultureInfo.NumberFormat.NegativeSign)
{
return true;
}
- if (text.Count(c => c == SpecificCultureInfo.NumberFormat.PositiveSign[0]) > 1
- || text.Count(c => c == SpecificCultureInfo.NumberFormat.NegativeSign[0]) > 1
- || text.Count(c => c == SpecificCultureInfo.NumberFormat.NumberGroupSeparator[0]) > 1)
+ if (text.Count(c => c == this.SpecificCultureInfo.NumberFormat.PositiveSign[0]) > 1
+ || text.Count(c => c == this.SpecificCultureInfo.NumberFormat.NegativeSign[0]) > 1
+ || text.Count(c => c == this.SpecificCultureInfo.NumberFormat.NumberGroupSeparator[0]) > 1)
{
return false;
}
- var isNumeric = NumericInputMode == NumericInput.Numbers
- || ParsingNumberStyle.HasFlag(NumberStyles.AllowHexSpecifier)
- || ParsingNumberStyle == NumberStyles.HexNumber
- || ParsingNumberStyle == NumberStyles.Integer
- || ParsingNumberStyle == NumberStyles.Number;
+ var isNumeric = this.NumericInputMode == NumericInput.Numbers
+ || this.ParsingNumberStyle.HasFlag(NumberStyles.AllowHexSpecifier)
+ || this.ParsingNumberStyle == NumberStyles.HexNumber
+ || this.ParsingNumberStyle == NumberStyles.Integer
+ || this.ParsingNumberStyle == NumberStyles.Number;
- var isHex = NumericInputMode == NumericInput.Numbers
- || ParsingNumberStyle.HasFlag(NumberStyles.AllowHexSpecifier)
- || ParsingNumberStyle == NumberStyles.HexNumber;
+ var isHex = this.NumericInputMode == NumericInput.Numbers
+ || this.ParsingNumberStyle.HasFlag(NumberStyles.AllowHexSpecifier)
+ || this.ParsingNumberStyle == NumberStyles.HexNumber;
- text = TryGetNumberFromText(text, isHex);
+ var number = this.TryGetNumberFromText(text, isHex);
// If we are only accepting numbers then attempt to parse as an integer.
if (isNumeric)
{
- return ConvertNumber(text, out convertedValue);
+ return this.ConvertNumber(number, out convertedValue);
}
- if (text == SpecificCultureInfo.NumberFormat.NumberDecimalSeparator
- || text == SpecificCultureInfo.NumberFormat.CurrencyDecimalSeparator
- || text == SpecificCultureInfo.NumberFormat.PercentDecimalSeparator)
+ if (number == this.SpecificCultureInfo.NumberFormat.NumberDecimalSeparator
+ || number == this.SpecificCultureInfo.NumberFormat.CurrencyDecimalSeparator
+ || number == this.SpecificCultureInfo.NumberFormat.PercentDecimalSeparator)
{
return true;
}
- if (!double.TryParse(text, ParsingNumberStyle, SpecificCultureInfo, out convertedValue))
+ if (!double.TryParse(number, this.ParsingNumberStyle, this.SpecificCultureInfo, out convertedValue))
{
return false;
}
@@ -1236,15 +1313,15 @@ private bool ValidateText(string text, out double convertedValue)
private bool ConvertNumber(string text, out double convertedValue)
{
- if (text.Any(c => c == SpecificCultureInfo.NumberFormat.NumberDecimalSeparator[0]
- || c == SpecificCultureInfo.NumberFormat.PercentDecimalSeparator[0]
- || c == SpecificCultureInfo.NumberFormat.CurrencyDecimalSeparator[0]))
+ if (text.Any(c => c == this.SpecificCultureInfo.NumberFormat.NumberDecimalSeparator[0]
+ || c == this.SpecificCultureInfo.NumberFormat.PercentDecimalSeparator[0]
+ || c == this.SpecificCultureInfo.NumberFormat.CurrencyDecimalSeparator[0]))
{
convertedValue = 0d;
return false;
}
- if (!long.TryParse(text, ParsingNumberStyle, SpecificCultureInfo, out var convertedInt))
+ if (!long.TryParse(text, this.ParsingNumberStyle, this.SpecificCultureInfo, out var convertedInt))
{
convertedValue = convertedInt;
return false;
diff --git a/src/MahApps.Metro/Themes/NumericUpDown.xaml b/src/MahApps.Metro/Themes/NumericUpDown.xaml
index c4f9ae92d2..2b2d660c04 100644
--- a/src/MahApps.Metro/Themes/NumericUpDown.xaml
+++ b/src/MahApps.Metro/Themes/NumericUpDown.xaml
@@ -88,6 +88,7 @@
Width="{TemplateBinding UpDownButtonsWidth}"
Margin="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={StaticResource ThicknessBindingConverter}, ConverterParameter={x:Static Converters:ThicknessSideType.Left}}"
Delay="{TemplateBinding Delay}"
+ Focusable="{TemplateBinding UpDownButtonsFocusable}"
Foreground="{TemplateBinding Foreground}"
IsTabStop="False"
Style="{DynamicResource ChromelessButtonStyle}">
@@ -104,6 +105,7 @@
Margin="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={StaticResource ThicknessBindingConverter}, ConverterParameter={x:Static Converters:ThicknessSideType.Right}}"
VerticalContentAlignment="Center"
Delay="{TemplateBinding Delay}"
+ Focusable="{TemplateBinding UpDownButtonsFocusable}"
Foreground="{TemplateBinding Foreground}"
IsTabStop="False"
Style="{DynamicResource ChromelessButtonStyle}">