Skip to content

Commit

Permalink
Bugfix: Format-Text must return parsed value, else value in textbox w…
Browse files Browse the repository at this point in the history
…ill be overwritten with "LastEditingNumericValue" if "IsUpdateValueWhenLostFocus" is enabled on lost focus

- Consolidate "FormatText" in base class (it´s nearly the same code in all derived classes)
- introduce abstract "ParseText" and type specific implementations for usage in in "FormatText", which was the only difference in the several implementations#
- return parsed value in "FormatText" to be used in e.g. _PART_TextBox_LostFocus, where it is assgined to "Value" (here´s were "Value" got lost)
- activate "IsUpdateValueWhenLostFocus" in demo application
  • Loading branch information
Jürgen Holzer committed Jan 10, 2023
1 parent 8c593b0 commit a756b40
Show file tree
Hide file tree
Showing 24 changed files with 119 additions and 558 deletions.
1 change: 1 addition & 0 deletions source/Demo/UpDownDemoLib/Views/ByteUpDownDemo.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
IsDisplayLengthFixed="True"
IsMouseDragEnabled="{Binding ElementName=IsMouseDragEnabledCheckBox, Path=IsChecked}"
IsReadOnly="False"
IsUpdateValueWhenLostFocus="True"
MaxValue="{Binding MaximumValue}"
MinValue="{Binding MinimumValue}"
MouseWheelAccelaratorKey="{Binding AccelModifierKey, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Expand Down
1 change: 1 addition & 0 deletions source/Demo/UpDownDemoLib/Views/DecimalUpDownDemo.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
IsDisplayLengthFixed="True"
IsMouseDragEnabled="{Binding ElementName=IsMouseDragEnabledCheckBox, Path=IsChecked}"
IsReadOnly="False"
IsUpdateValueWhenLostFocus="True"
LargeStepSize="{Binding LargeStepSize, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
MaxValue="{Binding MaximumValue}"
MinValue="{Binding MinimumValue}"
Expand Down
1 change: 1 addition & 0 deletions source/Demo/UpDownDemoLib/Views/DoubleUpDownDemo.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
IsDisplayLengthFixed="True"
IsMouseDragEnabled="{Binding ElementName=IsMouseDragEnabledCheckBox, Path=IsChecked}"
IsReadOnly="False"
IsUpdateValueWhenLostFocus="True"
LargeStepSize="{Binding LargeStepSize, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
MaxValue="{Binding MaximumValue}"
MinValue="{Binding MinimumValue}"
Expand Down
1 change: 1 addition & 0 deletions source/Demo/UpDownDemoLib/Views/FloatUpDownDemo.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
IsDisplayLengthFixed="True"
IsMouseDragEnabled="{Binding ElementName=IsMouseDragEnabledCheckBox, Path=IsChecked}"
IsReadOnly="False"
IsUpdateValueWhenLostFocus="True"
LargeStepSize="{Binding LargeStepSize, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
MaxValue="{Binding MaximumValue}"
MinValue="{Binding MinimumValue}"
Expand Down
1 change: 1 addition & 0 deletions source/Demo/UpDownDemoLib/Views/LongUpDownDemo.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
IsDisplayLengthFixed="True"
IsMouseDragEnabled="{Binding ElementName=IsMouseDragEnabledCheckBox, Path=IsChecked}"
IsReadOnly="False"
IsUpdateValueWhenLostFocus="True"
LargeStepSize="{Binding LargeStepSize, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
MaxValue="{Binding MaximumValue}"
MinValue="{Binding MinimumValue}"
Expand Down
1 change: 1 addition & 0 deletions source/Demo/UpDownDemoLib/Views/NumericUpDownDemo.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
IsDisplayLengthFixed="True"
IsMouseDragEnabled="{Binding ElementName=IsMouseDragEnabledCheckBox, Path=IsChecked}"
IsReadOnly="False"
IsUpdateValueWhenLostFocus="True"
LargeStepSize="{Binding LargeStepSize, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
MaxValue="{Binding MaximumValue}"
MinValue="{Binding MinimumValue}"
Expand Down
1 change: 1 addition & 0 deletions source/Demo/UpDownDemoLib/Views/PercentageUpDownDemo.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
IsDisplayLengthFixed="True"
IsMouseDragEnabled="{Binding ElementName=IsMouseDragEnabledCheckBox, Path=IsChecked}"
IsReadOnly="False"
IsUpdateValueWhenLostFocus="True"
LargeStepSize="{Binding LargeStepSize, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
MaxValue="{Binding MaximumValue, Converter={StaticResource FactorToDoubleConverter}, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
MinValue="{Binding MinimumValue, Converter={StaticResource FactorToDoubleConverter}, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Expand Down
1 change: 1 addition & 0 deletions source/Demo/UpDownDemoLib/Views/SByteUpDownDemo.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
IsDisplayLengthFixed="True"
IsMouseDragEnabled="{Binding ElementName=IsMouseDragEnabledCheckBox, Path=IsChecked}"
IsReadOnly="False"
IsUpdateValueWhenLostFocus="True"
LargeStepSize="{Binding LargeStepSize, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
MaxValue="{Binding MaximumValue}"
MinValue="{Binding MinimumValue}"
Expand Down
1 change: 1 addition & 0 deletions source/Demo/UpDownDemoLib/Views/ShortUpDownDemo.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
IsDisplayLengthFixed="True"
IsMouseDragEnabled="{Binding ElementName=IsMouseDragEnabledCheckBox, Path=IsChecked}"
IsReadOnly="False"
IsUpdateValueWhenLostFocus="True"
LargeStepSize="{Binding LargeStepSize, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
MaxValue="{Binding MaximumValue}"
MinValue="{Binding MinimumValue}"
Expand Down
1 change: 1 addition & 0 deletions source/Demo/UpDownDemoLib/Views/UIntegerUpDownDemo.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
IsDisplayLengthFixed="True"
IsMouseDragEnabled="{Binding ElementName=IsMouseDragEnabledCheckBox, Path=IsChecked}"
IsReadOnly="False"
IsUpdateValueWhenLostFocus="True"
LargeStepSize="{Binding LargeStepSize, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
MaxValue="{Binding MaximumValue}"
MinValue="{Binding MinimumValue}"
Expand Down
1 change: 1 addition & 0 deletions source/Demo/UpDownDemoLib/Views/ULongUpDownDemo.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
IsDisplayLengthFixed="True"
IsMouseDragEnabled="{Binding ElementName=IsMouseDragEnabledCheckBox, Path=IsChecked}"
IsReadOnly="False"
IsUpdateValueWhenLostFocus="True"
LargeStepSize="{Binding LargeStepSize, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
MaxValue="{Binding MaximumValue}"
MinValue="{Binding MinimumValue}"
Expand Down
1 change: 1 addition & 0 deletions source/Demo/UpDownDemoLib/Views/UShortUpDownDemo.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
IsDisplayLengthFixed="True"
IsMouseDragEnabled="{Binding ElementName=IsMouseDragEnabledCheckBox, Path=IsChecked}"
IsReadOnly="False"
IsUpdateValueWhenLostFocus="True"
LargeStepSize="{Binding LargeStepSize, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
MaxValue="{Binding MaximumValue}"
MinValue="{Binding MinimumValue}"
Expand Down
52 changes: 38 additions & 14 deletions source/NumericUpDownLib/Base/AbstractBaseUpDown.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ namespace NumericUpDownLib.Base
using NumericUpDownLib.Enums;
using NumericUpDownLib.Models;
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
Expand Down Expand Up @@ -1159,21 +1160,44 @@ protected string FormatNumber(T number)
}

/// <summary>
/// Checks if the current string entered in the textbox is:
/// 1) A valid number (syntax)
/// 2) within bounds (Min &lt;= number &lt;= Max )
///
/// 3) adjusts the string if it appears to be invalid and
///
/// 4) <paramref name="formatNumber"/> true:
/// Applies the FormatString property to format the text in a certain way
/// </summary>
/// <param name="text"></param>
/// <param name="formatNumber"></param>
/// <returns>the value of the string with special format</returns>
protected abstract T FormatText(string text, bool formatNumber = true);
/// Checks if the current string entered in the textbox is:
/// 1) A valid number (syntax)
/// 2) within bounds (Min &lt;= number &lt;= Max )
///
/// 3) adjusts the string if it appears to be invalid and
///
/// 4) <paramref name="formatNumber"/> true:
/// Applies the FormatString property to format the text in a certain way
/// </summary>
/// <param name="text"></param>
/// <param name="formatNumber"></param>
/// <returns>the value of the string with special format</returns>
protected T FormatText(string text, bool formatNumber = true)
{
if (_PART_TextBox == null)
return Value;

/// <summary>
T number = default;
// Does this text represent a valid number ?
if (ParseText(text, out number))
{
number = CoerceValue(number);

_PART_TextBox.Text = FormatNumber(number);
_PART_TextBox.SelectionStart = 0;

return number;
}

// Reset to last value since string does not appear to represent a number
_PART_TextBox.SelectionStart = 0;
_PART_TextBox.Text = FormatNumber(Value);
return LastEditingNumericValue;
}

protected abstract bool ParseText(string text, out T number);

/// <summary>
/// Verify the text is valid or not while use is typing
/// </summary>
/// <param name="text"></param>
Expand Down
68 changes: 12 additions & 56 deletions source/NumericUpDownLib/ByteUpDown.cs
Original file line number Diff line number Diff line change
Expand Up @@ -321,62 +321,18 @@ protected override bool VerifyText(string text, ref Byte tempValue)
return false;
}

/// <summary>
/// Checks if the current string entered in the textbox is valid
/// and conforms to a known format
/// (<see cref="AbstractBaseUpDown{T}"/> base method for more details).
/// </summary>
/// <param name="text"></param>
/// <param name="formatNumber"></param>
protected override byte FormatText(string text, bool formatNumber = true)
{
if (_PART_TextBox == null)
return Value;

byte number = 0;
// Does this text represent a valid number ?
if (byte.TryParse(text, base.NumberStyle,
CultureInfo.CurrentCulture, out number) == true)
{
// yes -> but is the number within bounds?
if (number > MaxValue)
{
// Larger than allowed maximum
_PART_TextBox.Text = FormatNumber(MaxValue);
_PART_TextBox.SelectionStart = 0;
}
else
{
if (number < MinValue)
{
// Smaller than allowed minimum
_PART_TextBox.Text = FormatNumber(MinValue);
_PART_TextBox.SelectionStart = 0;
}
else
{
// Number is valid and within bounds, just format if requested
if (formatNumber == true)
_PART_TextBox.Text = FormatNumber(number);
}
}
}
else
{
// Reset to last value since string does not appear to represent a number
_PART_TextBox.SelectionStart = 0;
_PART_TextBox.Text = FormatNumber(Value);
}
return LastEditingNumericValue;
}

/// <summary>
/// Determines whether the step size in the <paramref name="value"/> parameter
/// is larger 0 (valid) or not.
/// </summary>
/// <param name="value">returns true for valid values, otherwise false.</param>
/// <returns></returns>
private static bool IsValidStepSizeReading(object value)
protected override bool ParseText(string text, out byte number)
{
return byte.TryParse(text, base.NumberStyle, CultureInfo.CurrentCulture, out number);
}

/// <summary>
/// Determines whether the step size in the <paramref name="value"/> parameter
/// is larger 0 (valid) or not.
/// </summary>
/// <param name="value">returns true for valid values, otherwise false.</param>
/// <returns></returns>
private static bool IsValidStepSizeReading(object value)
{
byte v = (byte)value;
return (v > 0);
Expand Down
67 changes: 12 additions & 55 deletions source/NumericUpDownLib/DecimalUpDown.cs
Original file line number Diff line number Diff line change
Expand Up @@ -322,61 +322,18 @@ protected override bool VerifyText(string text, ref Decimal tempValue)
return false;
}

/// <summary>
/// Checks if the current string entered in the textbox is valid
/// and conforms to a known format
/// (<see cref="AbstractBaseUpDown{T}"/> base method for more details).
/// </summary>
/// <param name="text"></param>
/// <param name="formatNumber"></param>
protected override decimal FormatText(string text, bool formatNumber = true)
{
if (_PART_TextBox == null)
return Value;
decimal number = 0;
// Does this text represent a valid number ?
if (decimal.TryParse(text, base.NumberStyle,
CultureInfo.CurrentCulture, out number) == true)
{
// yes -> but is the number within bounds?
if (number > MaxValue)
{
// Larger than allowed maximum
_PART_TextBox.Text = FormatNumber(MaxValue);
_PART_TextBox.SelectionStart = 0;
}
else
{
if (number < MinValue)
{
// Smaller than allowed minimum
_PART_TextBox.Text = FormatNumber(MinValue);
_PART_TextBox.SelectionStart = 0;
}
else
{
// Number is valid and within bounds, just format if requested
if (formatNumber == true)
_PART_TextBox.Text = FormatNumber(number);
}
}
}
else
{
// Reset to last value since string does not appear to represent a number
_PART_TextBox.SelectionStart = 0;
_PART_TextBox.Text = FormatNumber(Value);
}
return LastEditingNumericValue;
}

/// <summary>
/// Determines whether the step size in the <paramref name="value"/> parameter
/// is larger 0 (valid) or not.
/// </summary>
/// <param name="value">returns true for valid values, otherwise false.</param>
/// <returns></returns>
private static bool IsValidStepSizeReading(object value)
protected override bool ParseText(string text, out decimal number)
{
return decimal.TryParse(text, base.NumberStyle, CultureInfo.CurrentCulture, out number);
}

/// <summary>
/// Determines whether the step size in the <paramref name="value"/> parameter
/// is larger 0 (valid) or not.
/// </summary>
/// <param name="value">returns true for valid values, otherwise false.</param>
/// <returns></returns>
private static bool IsValidStepSizeReading(object value)
{
decimal v = (decimal)value;
return (v > 0);
Expand Down
51 changes: 4 additions & 47 deletions source/NumericUpDownLib/DoubleUpDown.cs
Original file line number Diff line number Diff line change
Expand Up @@ -325,53 +325,10 @@ protected override bool VerifyText(string text, ref double tempValue)
return false;
}

/// <summary>
/// Checks if the current string entered in the textbox is valid
/// and conforms to a known format
/// (<see cref="AbstractBaseUpDown{T}"/> base method for more details).
/// </summary>
/// <param name="text"></param>
/// <param name="formatNumber"></param>
protected override double FormatText(string text, bool formatNumber = true)
{
if (_PART_TextBox == null)
return Value;
double number = 0;
// Does this text represent a valid number ?
if (double.TryParse(text, base.NumberStyle,
CultureInfo.CurrentCulture, out number) == true)
{
// yes -> but is the number within bounds?
if (number > MaxValue)
{
// Larger than allowed maximum
_PART_TextBox.Text = FormatNumber(MaxValue);
_PART_TextBox.SelectionStart = 0;
}
else
{
if (number < MinValue)
{
// Smaller than allowed minimum
_PART_TextBox.Text = FormatNumber(MinValue);
_PART_TextBox.SelectionStart = 0;
}
else
{
// Number is valid and within bounds, just format if requested
if (formatNumber == true)
_PART_TextBox.Text = FormatNumber(number);
}
}
}
else
{
// Reset to last value since string does not appear to represent a number
_PART_TextBox.SelectionStart = 0;
_PART_TextBox.Text = FormatNumber(Value);
}
return LastEditingNumericValue;
}
protected override bool ParseText(string text, out double number)
{
return double.TryParse(text, base.NumberStyle, CultureInfo.CurrentCulture, out number);
}

/// <summary>
/// Determines whether the step size in the <paramref name="value"/> parameter
Expand Down
Loading

0 comments on commit a756b40

Please sign in to comment.