|
|
@@ -45,10 +45,18 @@ namespace Avalonia.Controls
|
|
|
/// <summary>
|
|
|
/// Defines the <see cref="CultureInfo"/> property.
|
|
|
/// </summary>
|
|
|
+ [Obsolete]
|
|
|
public static readonly DirectProperty<NumericUpDown, CultureInfo> CultureInfoProperty =
|
|
|
AvaloniaProperty.RegisterDirect<NumericUpDown, CultureInfo>(nameof(CultureInfo), o => o.CultureInfo,
|
|
|
(o, v) => o.CultureInfo = v, CultureInfo.CurrentCulture);
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Defines the <see cref="NumberFormat"/> property.
|
|
|
+ /// </summary>
|
|
|
+ public static readonly DirectProperty<NumericUpDown, NumberFormatInfo> NumberFormatProperty =
|
|
|
+ AvaloniaProperty.RegisterDirect<NumericUpDown, NumberFormatInfo>(nameof(NumberFormat), o => o.NumberFormat,
|
|
|
+ (o, v) => o.NumberFormat = v, NumberFormatInfo.CurrentInfo);
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Defines the <see cref="FormatString"/> property.
|
|
|
/// </summary>
|
|
|
@@ -58,8 +66,8 @@ namespace Avalonia.Controls
|
|
|
/// <summary>
|
|
|
/// Defines the <see cref="Increment"/> property.
|
|
|
/// </summary>
|
|
|
- public static readonly StyledProperty<double> IncrementProperty =
|
|
|
- AvaloniaProperty.Register<NumericUpDown, double>(nameof(Increment), 1.0d, coerce: OnCoerceIncrement);
|
|
|
+ public static readonly StyledProperty<decimal> IncrementProperty =
|
|
|
+ AvaloniaProperty.Register<NumericUpDown, decimal>(nameof(Increment), 1.0m, coerce: OnCoerceIncrement);
|
|
|
|
|
|
/// <summary>
|
|
|
/// Defines the <see cref="IsReadOnly"/> property.
|
|
|
@@ -70,14 +78,14 @@ namespace Avalonia.Controls
|
|
|
/// <summary>
|
|
|
/// Defines the <see cref="Maximum"/> property.
|
|
|
/// </summary>
|
|
|
- public static readonly StyledProperty<double> MaximumProperty =
|
|
|
- AvaloniaProperty.Register<NumericUpDown, double>(nameof(Maximum), double.MaxValue, coerce: OnCoerceMaximum);
|
|
|
+ public static readonly StyledProperty<decimal> MaximumProperty =
|
|
|
+ AvaloniaProperty.Register<NumericUpDown, decimal>(nameof(Maximum), decimal.MaxValue, coerce: OnCoerceMaximum);
|
|
|
|
|
|
/// <summary>
|
|
|
/// Defines the <see cref="Minimum"/> property.
|
|
|
/// </summary>
|
|
|
- public static readonly StyledProperty<double> MinimumProperty =
|
|
|
- AvaloniaProperty.Register<NumericUpDown, double>(nameof(Minimum), double.MinValue, coerce: OnCoerceMinimum);
|
|
|
+ public static readonly StyledProperty<decimal> MinimumProperty =
|
|
|
+ AvaloniaProperty.Register<NumericUpDown, decimal>(nameof(Minimum), decimal.MinValue, coerce: OnCoerceMinimum);
|
|
|
|
|
|
/// <summary>
|
|
|
/// Defines the <see cref="ParsingNumberStyle"/> property.
|
|
|
@@ -96,8 +104,8 @@ namespace Avalonia.Controls
|
|
|
/// <summary>
|
|
|
/// Defines the <see cref="Value"/> property.
|
|
|
/// </summary>
|
|
|
- public static readonly DirectProperty<NumericUpDown, double> ValueProperty =
|
|
|
- AvaloniaProperty.RegisterDirect<NumericUpDown, double>(nameof(Value), updown => updown.Value,
|
|
|
+ public static readonly DirectProperty<NumericUpDown, decimal> ValueProperty =
|
|
|
+ AvaloniaProperty.RegisterDirect<NumericUpDown, decimal>(nameof(Value), updown => updown.Value,
|
|
|
(updown, v) => updown.Value = v, defaultBindingMode: BindingMode.TwoWay, enableDataValidation: true);
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -106,7 +114,6 @@ namespace Avalonia.Controls
|
|
|
public static readonly StyledProperty<string> WatermarkProperty =
|
|
|
AvaloniaProperty.Register<NumericUpDown, string>(nameof(Watermark));
|
|
|
|
|
|
-
|
|
|
/// <summary>
|
|
|
/// Defines the <see cref="HorizontalContentAlignment"/> property.
|
|
|
/// </summary>
|
|
|
@@ -121,7 +128,7 @@ namespace Avalonia.Controls
|
|
|
|
|
|
private IDisposable _textBoxTextChangedSubscription;
|
|
|
|
|
|
- private double _value;
|
|
|
+ private decimal _value;
|
|
|
private string _text;
|
|
|
private bool _internalValueSet;
|
|
|
private bool _clipValueToMinMax;
|
|
|
@@ -129,7 +136,8 @@ namespace Avalonia.Controls
|
|
|
private bool _isTextChangedFromUI;
|
|
|
private CultureInfo _cultureInfo;
|
|
|
private NumberStyles _parsingNumberStyle = NumberStyles.Any;
|
|
|
-
|
|
|
+ private NumberFormatInfo _numberFormat;
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Gets the Spinner template part.
|
|
|
/// </summary>
|
|
|
@@ -179,10 +187,25 @@ namespace Avalonia.Controls
|
|
|
/// <summary>
|
|
|
/// Gets or sets the current CultureInfo.
|
|
|
/// </summary>
|
|
|
+ [Obsolete("CultureInfo is obsolete, please use NumberFormat instead.")]
|
|
|
public CultureInfo CultureInfo
|
|
|
{
|
|
|
get { return _cultureInfo; }
|
|
|
- set { SetAndRaise(CultureInfoProperty, ref _cultureInfo, value); }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ SetAndRaise(CultureInfoProperty, ref _cultureInfo, value);
|
|
|
+ //Set and Raise the NumberFormatProperty when CultureInfo is changed.
|
|
|
+ SetAndRaise(NumberFormatProperty, ref _numberFormat, value?.NumberFormat);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Gets or sets the current NumberFormatInfo
|
|
|
+ /// </summary>
|
|
|
+ public NumberFormatInfo NumberFormat
|
|
|
+ {
|
|
|
+ get { return _numberFormat; }
|
|
|
+ set { SetAndRaise(NumberFormatProperty, ref _numberFormat, value); }
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -197,7 +220,7 @@ namespace Avalonia.Controls
|
|
|
/// <summary>
|
|
|
/// Gets or sets the amount in which to increment the <see cref="Value"/>.
|
|
|
/// </summary>
|
|
|
- public double Increment
|
|
|
+ public decimal Increment
|
|
|
{
|
|
|
get { return GetValue(IncrementProperty); }
|
|
|
set { SetValue(IncrementProperty, value); }
|
|
|
@@ -215,7 +238,7 @@ namespace Avalonia.Controls
|
|
|
/// <summary>
|
|
|
/// Gets or sets the maximum allowed value.
|
|
|
/// </summary>
|
|
|
- public double Maximum
|
|
|
+ public decimal Maximum
|
|
|
{
|
|
|
get { return GetValue(MaximumProperty); }
|
|
|
set { SetValue(MaximumProperty, value); }
|
|
|
@@ -224,7 +247,7 @@ namespace Avalonia.Controls
|
|
|
/// <summary>
|
|
|
/// Gets or sets the minimum allowed value.
|
|
|
/// </summary>
|
|
|
- public double Minimum
|
|
|
+ public decimal Minimum
|
|
|
{
|
|
|
get { return GetValue(MinimumProperty); }
|
|
|
set { SetValue(MinimumProperty, value); }
|
|
|
@@ -251,7 +274,7 @@ namespace Avalonia.Controls
|
|
|
/// <summary>
|
|
|
/// Gets or sets the value.
|
|
|
/// </summary>
|
|
|
- public double Value
|
|
|
+ public decimal Value
|
|
|
{
|
|
|
get { return _value; }
|
|
|
set
|
|
|
@@ -270,7 +293,6 @@ namespace Avalonia.Controls
|
|
|
set { SetValue(WatermarkProperty, value); }
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/// <summary>
|
|
|
/// Gets or sets the horizontal alignment of the content within the control.
|
|
|
/// </summary>
|
|
|
@@ -311,6 +333,7 @@ namespace Avalonia.Controls
|
|
|
static NumericUpDown()
|
|
|
{
|
|
|
CultureInfoProperty.Changed.Subscribe(OnCultureInfoChanged);
|
|
|
+ NumberFormatProperty.Changed.Subscribe(OnNumberFormatChanged);
|
|
|
FormatStringProperty.Changed.Subscribe(FormatStringChanged);
|
|
|
IncrementProperty.Changed.Subscribe(IncrementChanged);
|
|
|
IsReadOnlyProperty.Changed.Subscribe(OnIsReadOnlyChanged);
|
|
|
@@ -397,6 +420,19 @@ namespace Avalonia.Controls
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Called when the <see cref="NumberFormat"/> property value changed.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="oldValue">The old value.</param>
|
|
|
+ /// <param name="newValue">The new value.</param>
|
|
|
+ protected virtual void OnNumberFormatChanged(NumberFormatInfo oldValue, NumberFormatInfo newValue)
|
|
|
+ {
|
|
|
+ if (IsInitialized)
|
|
|
+ {
|
|
|
+ SyncTextAndValueProperties(false, null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Called when the <see cref="FormatString"/> property value changed.
|
|
|
/// </summary>
|
|
|
@@ -415,7 +451,7 @@ namespace Avalonia.Controls
|
|
|
/// </summary>
|
|
|
/// <param name="oldValue">The old value.</param>
|
|
|
/// <param name="newValue">The new value.</param>
|
|
|
- protected virtual void OnIncrementChanged(double oldValue, double newValue)
|
|
|
+ protected virtual void OnIncrementChanged(decimal oldValue, decimal newValue)
|
|
|
{
|
|
|
if (IsInitialized)
|
|
|
{
|
|
|
@@ -438,7 +474,7 @@ namespace Avalonia.Controls
|
|
|
/// </summary>
|
|
|
/// <param name="oldValue">The old value.</param>
|
|
|
/// <param name="newValue">The new value.</param>
|
|
|
- protected virtual void OnMaximumChanged(double oldValue, double newValue)
|
|
|
+ protected virtual void OnMaximumChanged(decimal oldValue, decimal newValue)
|
|
|
{
|
|
|
if (IsInitialized)
|
|
|
{
|
|
|
@@ -455,7 +491,7 @@ namespace Avalonia.Controls
|
|
|
/// </summary>
|
|
|
/// <param name="oldValue">The old value.</param>
|
|
|
/// <param name="newValue">The new value.</param>
|
|
|
- protected virtual void OnMinimumChanged(double oldValue, double newValue)
|
|
|
+ protected virtual void OnMinimumChanged(decimal oldValue, decimal newValue)
|
|
|
{
|
|
|
if (IsInitialized)
|
|
|
{
|
|
|
@@ -485,7 +521,7 @@ namespace Avalonia.Controls
|
|
|
/// </summary>
|
|
|
/// <param name="oldValue">The old value.</param>
|
|
|
/// <param name="newValue">The new value.</param>
|
|
|
- protected virtual void OnValueChanged(double oldValue, double newValue)
|
|
|
+ protected virtual void OnValueChanged(decimal oldValue, decimal newValue)
|
|
|
{
|
|
|
if (!_internalValueSet && IsInitialized)
|
|
|
{
|
|
|
@@ -501,7 +537,7 @@ namespace Avalonia.Controls
|
|
|
/// Called when the <see cref="Increment"/> property has to be coerced.
|
|
|
/// </summary>
|
|
|
/// <param name="baseValue">The value.</param>
|
|
|
- protected virtual double OnCoerceIncrement(double baseValue)
|
|
|
+ protected virtual decimal OnCoerceIncrement(decimal baseValue)
|
|
|
{
|
|
|
return baseValue;
|
|
|
}
|
|
|
@@ -510,7 +546,7 @@ namespace Avalonia.Controls
|
|
|
/// Called when the <see cref="Maximum"/> property has to be coerced.
|
|
|
/// </summary>
|
|
|
/// <param name="baseValue">The value.</param>
|
|
|
- protected virtual double OnCoerceMaximum(double baseValue)
|
|
|
+ protected virtual decimal OnCoerceMaximum(decimal baseValue)
|
|
|
{
|
|
|
return Math.Max(baseValue, Minimum);
|
|
|
}
|
|
|
@@ -519,7 +555,7 @@ namespace Avalonia.Controls
|
|
|
/// Called when the <see cref="Minimum"/> property has to be coerced.
|
|
|
/// </summary>
|
|
|
/// <param name="baseValue">The value.</param>
|
|
|
- protected virtual double OnCoerceMinimum(double baseValue)
|
|
|
+ protected virtual decimal OnCoerceMinimum(decimal baseValue)
|
|
|
{
|
|
|
return Math.Min(baseValue, Maximum);
|
|
|
}
|
|
|
@@ -528,7 +564,7 @@ namespace Avalonia.Controls
|
|
|
/// Called when the <see cref="Value"/> property has to be coerced.
|
|
|
/// </summary>
|
|
|
/// <param name="baseValue">The value.</param>
|
|
|
- protected virtual double OnCoerceValue(double baseValue)
|
|
|
+ protected virtual decimal OnCoerceValue(decimal baseValue)
|
|
|
{
|
|
|
return baseValue;
|
|
|
}
|
|
|
@@ -562,7 +598,7 @@ namespace Avalonia.Controls
|
|
|
/// </summary>
|
|
|
/// <param name="oldValue">The old value.</param>
|
|
|
/// <param name="newValue">The new value.</param>
|
|
|
- protected virtual void RaiseValueChangedEvent(double oldValue, double newValue)
|
|
|
+ protected virtual void RaiseValueChangedEvent(decimal oldValue, decimal newValue)
|
|
|
{
|
|
|
var e = new NumericUpDownValueChangedEventArgs(ValueChangedEvent, oldValue, newValue);
|
|
|
RaiseEvent(e);
|
|
|
@@ -571,9 +607,9 @@ namespace Avalonia.Controls
|
|
|
/// <summary>
|
|
|
/// Converts the formatted text to a value.
|
|
|
/// </summary>
|
|
|
- private double ConvertTextToValue(string text)
|
|
|
+ private decimal ConvertTextToValue(string text)
|
|
|
{
|
|
|
- double result = 0;
|
|
|
+ decimal result = 0;
|
|
|
|
|
|
if (string.IsNullOrEmpty(text))
|
|
|
{
|
|
|
@@ -609,10 +645,10 @@ namespace Avalonia.Controls
|
|
|
//Manage FormatString of type "{}{0:N2} °" (in xaml) or "{0:N2} °" in code-behind.
|
|
|
if (FormatString.Contains("{0"))
|
|
|
{
|
|
|
- return string.Format(CultureInfo, FormatString, Value);
|
|
|
+ return string.Format(NumberFormat, FormatString, Value);
|
|
|
}
|
|
|
|
|
|
- return Value.ToString(FormatString, CultureInfo);
|
|
|
+ return Value.ToString(FormatString, NumberFormat);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -674,6 +710,20 @@ namespace Avalonia.Controls
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Called when the <see cref="NumberFormat"/> property value changed.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="e">The event args.</param>
|
|
|
+ private static void OnNumberFormatChanged(AvaloniaPropertyChangedEventArgs e)
|
|
|
+ {
|
|
|
+ if (e.Sender is NumericUpDown upDown)
|
|
|
+ {
|
|
|
+ var oldValue = (NumberFormatInfo)e.OldValue;
|
|
|
+ var newValue = (NumberFormatInfo)e.NewValue;
|
|
|
+ upDown.OnNumberFormatChanged(oldValue, newValue);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Called when the <see cref="Increment"/> property value changed.
|
|
|
/// </summary>
|
|
|
@@ -682,8 +732,8 @@ namespace Avalonia.Controls
|
|
|
{
|
|
|
if (e.Sender is NumericUpDown upDown)
|
|
|
{
|
|
|
- var oldValue = (double)e.OldValue;
|
|
|
- var newValue = (double)e.NewValue;
|
|
|
+ var oldValue = (decimal)e.OldValue;
|
|
|
+ var newValue = (decimal)e.NewValue;
|
|
|
upDown.OnIncrementChanged(oldValue, newValue);
|
|
|
}
|
|
|
}
|
|
|
@@ -724,8 +774,8 @@ namespace Avalonia.Controls
|
|
|
{
|
|
|
if (e.Sender is NumericUpDown upDown)
|
|
|
{
|
|
|
- var oldValue = (double)e.OldValue;
|
|
|
- var newValue = (double)e.NewValue;
|
|
|
+ var oldValue = (decimal)e.OldValue;
|
|
|
+ var newValue = (decimal)e.NewValue;
|
|
|
upDown.OnMaximumChanged(oldValue, newValue);
|
|
|
}
|
|
|
}
|
|
|
@@ -738,8 +788,8 @@ namespace Avalonia.Controls
|
|
|
{
|
|
|
if (e.Sender is NumericUpDown upDown)
|
|
|
{
|
|
|
- var oldValue = (double)e.OldValue;
|
|
|
- var newValue = (double)e.NewValue;
|
|
|
+ var oldValue = (decimal)e.OldValue;
|
|
|
+ var newValue = (decimal)e.NewValue;
|
|
|
upDown.OnMinimumChanged(oldValue, newValue);
|
|
|
}
|
|
|
}
|
|
|
@@ -766,13 +816,13 @@ namespace Avalonia.Controls
|
|
|
{
|
|
|
if (e.Sender is NumericUpDown upDown)
|
|
|
{
|
|
|
- var oldValue = (double)e.OldValue;
|
|
|
- var newValue = (double)e.NewValue;
|
|
|
+ var oldValue = (decimal)e.OldValue;
|
|
|
+ var newValue = (decimal)e.NewValue;
|
|
|
upDown.OnValueChanged(oldValue, newValue);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void SetValueInternal(double value)
|
|
|
+ private void SetValueInternal(decimal value)
|
|
|
{
|
|
|
_internalValueSet = true;
|
|
|
try
|
|
|
@@ -785,7 +835,7 @@ namespace Avalonia.Controls
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private static double OnCoerceMaximum(IAvaloniaObject instance, double value)
|
|
|
+ private static decimal OnCoerceMaximum(IAvaloniaObject instance, decimal value)
|
|
|
{
|
|
|
if (instance is NumericUpDown upDown)
|
|
|
{
|
|
|
@@ -795,7 +845,7 @@ namespace Avalonia.Controls
|
|
|
return value;
|
|
|
}
|
|
|
|
|
|
- private static double OnCoerceMinimum(IAvaloniaObject instance, double value)
|
|
|
+ private static decimal OnCoerceMinimum(IAvaloniaObject instance, decimal value)
|
|
|
{
|
|
|
if (instance is NumericUpDown upDown)
|
|
|
{
|
|
|
@@ -805,7 +855,7 @@ namespace Avalonia.Controls
|
|
|
return value;
|
|
|
}
|
|
|
|
|
|
- private static double OnCoerceIncrement(IAvaloniaObject instance, double value)
|
|
|
+ private static decimal OnCoerceIncrement(IAvaloniaObject instance, decimal value)
|
|
|
{
|
|
|
if (instance is NumericUpDown upDown)
|
|
|
{
|
|
|
@@ -977,23 +1027,23 @@ namespace Avalonia.Controls
|
|
|
return parsedTextIsValid;
|
|
|
}
|
|
|
|
|
|
- private double ConvertTextToValueCore(string currentValueText, string text)
|
|
|
+ private decimal ConvertTextToValueCore(string currentValueText, string text)
|
|
|
{
|
|
|
- double result;
|
|
|
+ decimal result;
|
|
|
|
|
|
if (IsPercent(FormatString))
|
|
|
{
|
|
|
- result = decimal.ToDouble(ParsePercent(text, CultureInfo));
|
|
|
+ result = ParsePercent(text, NumberFormat);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// Problem while converting new text
|
|
|
- if (!double.TryParse(text, ParsingNumberStyle, CultureInfo, out var outputValue))
|
|
|
+ if (!decimal.TryParse(text, ParsingNumberStyle, NumberFormat, out var outputValue))
|
|
|
{
|
|
|
var shouldThrow = true;
|
|
|
|
|
|
// Check if CurrentValueText is also failing => it also contains special characters. ex : 90°
|
|
|
- if (!double.TryParse(currentValueText, ParsingNumberStyle, CultureInfo, out var _))
|
|
|
+ if (!decimal.TryParse(currentValueText, ParsingNumberStyle, NumberFormat, out var _))
|
|
|
{
|
|
|
// extract non-digit characters
|
|
|
var currentValueTextSpecialCharacters = currentValueText.Where(c => !char.IsDigit(c));
|
|
|
@@ -1006,7 +1056,7 @@ namespace Avalonia.Controls
|
|
|
text = text.Replace(character.ToString(), string.Empty);
|
|
|
}
|
|
|
// if without the special characters, parsing is good, do not throw
|
|
|
- if (double.TryParse(text, ParsingNumberStyle, CultureInfo, out outputValue))
|
|
|
+ if (decimal.TryParse(text, ParsingNumberStyle, NumberFormat, out outputValue))
|
|
|
{
|
|
|
shouldThrow = false;
|
|
|
}
|
|
|
@@ -1023,7 +1073,7 @@ namespace Avalonia.Controls
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
- private void ValidateMinMax(double value)
|
|
|
+ private void ValidateMinMax(decimal value)
|
|
|
{
|
|
|
if (value < Minimum)
|
|
|
{
|