forked from MaterialDesignInXAML/MaterialDesignInXamlToolkit
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
NumericUpDown control support decimals value, and the value for each …
…increase or decrease can be set. (MaterialDesignInXAML#3661) * Support decimals value, and the size of value for each increase or decrease can be set. * UpDown control support decimals, and the value for each increase or decrease can be set. * Updates to UpDownBase to support generic math on NET8 TODO: Need to fix XAMLTest to support the common generic base class so the generator stops choking * Updating UI tests Updated new XAMLTest library Added DeciamlUpDown tests --------- Co-authored-by: Kevin Bost <kevin@intellitect.com> Co-authored-by: Kevin Bost <kitokeboo@gmail.com>
- Loading branch information
Showing
13 changed files
with
617 additions
and
290 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
#if !NET8_0_OR_GREATER | ||
using System.Globalization; | ||
#endif | ||
|
||
namespace MaterialDesignThemes.Wpf; | ||
|
||
public class DecimalUpDown | ||
#if NET8_0_OR_GREATER | ||
: UpDownBase<decimal> | ||
#else | ||
: UpDownBase<decimal, DecimalArithmetic> | ||
#endif | ||
{ | ||
static DecimalUpDown() | ||
{ | ||
DefaultStyleKeyProperty.OverrideMetadata(typeof(DecimalUpDown), new FrameworkPropertyMetadata(typeof(DecimalUpDown))); | ||
} | ||
} | ||
|
||
#if !NET8_0_OR_GREATER | ||
public class DecimalArithmetic : IArithmetic<decimal> | ||
{ | ||
public decimal Add(decimal value1, decimal value2) => value1 + value2; | ||
|
||
public decimal Subtract(decimal value1, decimal value2) => value1 - value2; | ||
|
||
public int Compare(decimal value1, decimal value2) => value1.CompareTo(value2); | ||
|
||
public decimal MinValue() => decimal.MinValue; | ||
|
||
public decimal MaxValue() => decimal.MaxValue; | ||
|
||
public decimal One() => 1m; | ||
|
||
public decimal Max(decimal value1, decimal value2) => Math.Max(value1, value2); | ||
|
||
public decimal Min(decimal value1, decimal value2) => Math.Min(value1, value2); | ||
|
||
public bool TryParse(string text, IFormatProvider? formatProvider, out decimal value) | ||
=> decimal.TryParse(text, NumberStyles.Number, formatProvider, out value); | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,259 +1,41 @@ | ||
using System.ComponentModel; | ||
#if !NET8_0_OR_GREATER | ||
using System.Globalization; | ||
#endif | ||
|
||
namespace MaterialDesignThemes.Wpf; | ||
|
||
[TemplatePart(Name = IncreaseButtonPartName, Type = typeof(RepeatButton))] | ||
[TemplatePart(Name = DecreaseButtonPartName, Type = typeof(RepeatButton))] | ||
[TemplatePart(Name = TextBoxPartName, Type = typeof(TextBox))] | ||
public class NumericUpDown : Control | ||
public class NumericUpDown | ||
#if NET8_0_OR_GREATER | ||
: UpDownBase<int> | ||
#else | ||
: UpDownBase<int, IntArithmetic> | ||
#endif | ||
{ | ||
public const string IncreaseButtonPartName = "PART_IncreaseButton"; | ||
public const string DecreaseButtonPartName = "PART_DecreaseButton"; | ||
public const string TextBoxPartName = "PART_TextBox"; | ||
|
||
private TextBox? _textBoxField; | ||
private RepeatButton? _decreaseButton; | ||
private RepeatButton? _increaseButton; | ||
|
||
static NumericUpDown() | ||
{ | ||
DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericUpDown), new FrameworkPropertyMetadata(typeof(NumericUpDown))); | ||
} | ||
} | ||
|
||
#region DependencyProperties | ||
|
||
|
||
|
||
public object? IncreaseContent | ||
{ | ||
get => GetValue(IncreaseContentProperty); | ||
set => SetValue(IncreaseContentProperty, value); | ||
} | ||
|
||
// Using a DependencyProperty as the backing store for IncreaseContent. This enables animation, styling, binding, etc... | ||
public static readonly DependencyProperty IncreaseContentProperty = | ||
DependencyProperty.Register(nameof(IncreaseContent), typeof(object), typeof(NumericUpDown), new PropertyMetadata(null)); | ||
|
||
public object? DecreaseContent | ||
{ | ||
get => GetValue(DecreaseContentProperty); | ||
set => SetValue(DecreaseContentProperty, value); | ||
} | ||
|
||
// Using a DependencyProperty as the backing store for DecreaseContent. This enables animation, styling, binding, etc... | ||
public static readonly DependencyProperty DecreaseContentProperty = | ||
DependencyProperty.Register(nameof(DecreaseContent), typeof(object), typeof(NumericUpDown), new PropertyMetadata(null)); | ||
|
||
#region DependencyProperty : MinimumProperty | ||
public int Minimum | ||
{ | ||
get => (int)GetValue(MinimumProperty); | ||
set => SetValue(MinimumProperty, value); | ||
} | ||
public static readonly DependencyProperty MinimumProperty = | ||
DependencyProperty.Register(nameof(Minimum), typeof(int), typeof(NumericUpDown), new PropertyMetadata(int.MinValue, OnMinimumChanged)); | ||
|
||
private static void OnMinimumChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) | ||
{ | ||
NumericUpDown ctrl = (NumericUpDown)d; | ||
ctrl.CoerceValue(ValueProperty); | ||
ctrl.CoerceValue(MaximumProperty); | ||
} | ||
|
||
#endregion DependencyProperty : MinimumProperty | ||
|
||
#region DependencyProperty : MaximumProperty | ||
|
||
public int Maximum | ||
{ | ||
get => (int)GetValue(MaximumProperty); | ||
set => SetValue(MaximumProperty, value); | ||
} | ||
|
||
public static readonly DependencyProperty MaximumProperty = | ||
DependencyProperty.Register(nameof(Maximum), typeof(int), typeof(NumericUpDown), new PropertyMetadata(int.MaxValue, OnMaximumChanged, CoerceMaximum)); | ||
|
||
private static void OnMaximumChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) | ||
{ | ||
NumericUpDown ctrl = (NumericUpDown)d; | ||
ctrl.CoerceValue(ValueProperty); | ||
} | ||
|
||
private static object? CoerceMaximum(DependencyObject d, object? value) | ||
{ | ||
if (d is NumericUpDown numericUpDown && | ||
value is int numericValue) | ||
{ | ||
return Math.Max(numericUpDown.Minimum, numericValue); | ||
} | ||
return value; | ||
} | ||
|
||
#endregion DependencyProperty : MaximumProperty | ||
|
||
#region DependencyProperty : ValueProperty | ||
public int Value | ||
{ | ||
get => (int)GetValue(ValueProperty); | ||
set => SetValue(ValueProperty, value); | ||
} | ||
|
||
public static readonly DependencyProperty ValueProperty = | ||
DependencyProperty.Register(nameof(Value), typeof(int), typeof(NumericUpDown), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnNumericValueChanged, CoerceNumericValue)); | ||
|
||
private static void OnNumericValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) | ||
{ | ||
if (d is NumericUpDown numericUpDown) | ||
{ | ||
var args = new RoutedPropertyChangedEventArgs<int>((int)e.OldValue, (int)e.NewValue) | ||
{ | ||
RoutedEvent = ValueChangedEvent | ||
}; | ||
numericUpDown.RaiseEvent(args); | ||
if (numericUpDown._textBoxField is { } textBox) | ||
{ | ||
textBox.Text = ((int)e.NewValue).ToString(CultureInfo.CurrentUICulture); | ||
} | ||
|
||
if (numericUpDown._increaseButton is { } increaseButton) | ||
{ | ||
increaseButton.IsEnabled = numericUpDown.Value != numericUpDown.Maximum; | ||
} | ||
|
||
if (numericUpDown._decreaseButton is { } decreaseButton) | ||
{ | ||
decreaseButton.IsEnabled = numericUpDown.Value != numericUpDown.Minimum; | ||
} | ||
} | ||
} | ||
|
||
private static object? CoerceNumericValue(DependencyObject d, object? value) | ||
{ | ||
if (d is NumericUpDown numericUpDown && | ||
value is int numericValue) | ||
{ | ||
numericValue = Math.Min(numericUpDown.Maximum, numericValue); | ||
numericValue = Math.Max(numericUpDown.Minimum, numericValue); | ||
return numericValue; | ||
} | ||
return value; | ||
} | ||
#endregion ValueProperty | ||
|
||
#region DependencyProperty : AllowChangeOnScroll | ||
|
||
public bool AllowChangeOnScroll | ||
{ | ||
get => (bool)GetValue(AllowChangeOnScrollProperty); | ||
set => SetValue(AllowChangeOnScrollProperty, value); | ||
} | ||
|
||
public static readonly DependencyProperty AllowChangeOnScrollProperty = | ||
DependencyProperty.Register(nameof(AllowChangeOnScroll), typeof(bool), typeof(NumericUpDown), new PropertyMetadata(false)); | ||
|
||
#endregion | ||
|
||
#endregion DependencyProperties | ||
|
||
#region Event : ValueChangedEvent | ||
[Category("Behavior")] | ||
public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent(nameof(ValueChanged), RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<int>), typeof(NumericUpDown)); | ||
|
||
public event RoutedPropertyChangedEventHandler<int> ValueChanged | ||
{ | ||
add => AddHandler(ValueChangedEvent, value); | ||
remove => RemoveHandler(ValueChangedEvent, value); | ||
} | ||
#endregion Event : ValueChangedEvent | ||
|
||
public override void OnApplyTemplate() | ||
{ | ||
if (_increaseButton != null) | ||
_increaseButton.Click -= IncreaseButtonOnClick; | ||
|
||
if (_decreaseButton != null) | ||
_decreaseButton.Click -= DecreaseButtonOnClick; | ||
if (_textBoxField != null) | ||
_textBoxField.TextChanged -= OnTextBoxFocusLost; | ||
|
||
_increaseButton = GetTemplateChild(IncreaseButtonPartName) as RepeatButton; | ||
_decreaseButton = GetTemplateChild(DecreaseButtonPartName) as RepeatButton; | ||
_textBoxField = GetTemplateChild(TextBoxPartName) as TextBox; | ||
|
||
if (_increaseButton != null) | ||
_increaseButton.Click += IncreaseButtonOnClick; | ||
|
||
if (_decreaseButton != null) | ||
_decreaseButton.Click += DecreaseButtonOnClick; | ||
|
||
if (_textBoxField != null) | ||
{ | ||
_textBoxField.LostFocus += OnTextBoxFocusLost; | ||
_textBoxField.Text = Value.ToString(CultureInfo.CurrentUICulture); | ||
} | ||
|
||
base.OnApplyTemplate(); | ||
} | ||
#if !NET8_0_OR_GREATER | ||
public class IntArithmetic : IArithmetic<int> | ||
{ | ||
public int Add(int value1, int value2) => value1 + value2; | ||
|
||
private void OnTextBoxFocusLost(object sender, EventArgs e) | ||
{ | ||
if (_textBoxField is { } textBoxField) | ||
{ | ||
if (int.TryParse(textBoxField.Text, NumberStyles.Integer, CultureInfo.CurrentUICulture, out int numericValue)) | ||
{ | ||
SetCurrentValue(ValueProperty, numericValue); | ||
} | ||
else | ||
{ | ||
textBoxField.Text = Value.ToString(CultureInfo.CurrentUICulture); | ||
} | ||
} | ||
} | ||
public int Subtract(int value1, int value2) => value1 - value2; | ||
|
||
private void IncreaseButtonOnClick(object sender, RoutedEventArgs e) => OnIncrease(); | ||
public int Compare(int value1, int value2) => value1.CompareTo(value2); | ||
|
||
private void DecreaseButtonOnClick(object sender, RoutedEventArgs e) => OnDecrease(); | ||
public int MinValue() => int.MinValue; | ||
|
||
private void OnIncrease() | ||
{ | ||
SetCurrentValue(ValueProperty, Value + 1); | ||
} | ||
public int MaxValue() => int.MaxValue; | ||
public int One() => 1; | ||
|
||
private void OnDecrease() | ||
{ | ||
SetCurrentValue(ValueProperty, Value - 1); | ||
} | ||
public int Max(int value1, int value2) => Math.Max(value1, value2); | ||
|
||
protected override void OnPreviewKeyDown(KeyEventArgs e) | ||
{ | ||
if (e.Key == Key.Up) | ||
{ | ||
OnIncrease(); | ||
e.Handled = true; | ||
} | ||
else if (e.Key == Key.Down) | ||
{ | ||
OnDecrease(); | ||
e.Handled = true; | ||
} | ||
base.OnPreviewKeyDown(e); | ||
} | ||
public int Min(int value1, int value2) => Math.Min(value1, value2); | ||
|
||
protected override void OnPreviewMouseWheel(MouseWheelEventArgs e) | ||
{ | ||
if (IsKeyboardFocusWithin && AllowChangeOnScroll) | ||
{ | ||
if (e.Delta > 0) | ||
{ | ||
OnIncrease(); | ||
} | ||
else if (e.Delta < 0) | ||
{ | ||
OnDecrease(); | ||
} | ||
e.Handled = true; | ||
} | ||
base.OnPreviewMouseWheel(e); | ||
} | ||
public bool TryParse(string text, IFormatProvider? formatProvider, out int value) | ||
=> int.TryParse(text, NumberStyles.Integer, formatProvider, out value); | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.