Browse Source

fix(DoubleUpDown): revert to previous value on out-of-range input with ClipValueToMinMax=false

When ClipValueToMinMax=false and the user enters an out-of-range value
then tabs away (UpdateSourceTrigger=LostFocus), the control was silently
truncating digits to bring the value within Min/Max range. For example,
with Max=20000, typing 123456 would set the VM property to 12345 instead
of reverting to the original valid value.

Root cause: The intermediate valid values typed (e.g. 12345) were being
committed to the internal Value property during typing. On LostFocus,
when the final value (123456) was out of range, the text was reverted to
the last committed intermediate value instead of the pre-edit value.

Fix: Save the initial Value on focus gain (_initialValueOnFocus), and
restore it in the SyncTextAndValueProperties catch block when
ClipValueToMinMax=false and the user is not actively typing.

Fixes #1801
pull/1809/head
Harald Daltveit 4 months ago
parent
commit
9a90238178
  1. 17
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.Toolkit/Primitives/UpDownBase.cs

17
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.Toolkit/Primitives/UpDownBase.cs

@ -37,6 +37,7 @@ namespace Xceed.Wpf.Toolkit.Primitives
internal const string PART_Spinner = "PART_Spinner"; internal const string PART_Spinner = "PART_Spinner";
internal bool _isTextChangedFromUI; internal bool _isTextChangedFromUI;
private T _initialValueOnFocus;
private bool _isSyncingTextAndValueProperties; private bool _isSyncingTextAndValueProperties;
private bool _internalValueSet; private bool _internalValueSet;
@ -800,7 +801,13 @@ RoutedPropertyChangedEventHandler<object> ), typeof( UpDownBase<T> ) );
private void UpDownBase_IsKeyboardFocusWithinChanged( object sender, DependencyPropertyChangedEventArgs e ) private void UpDownBase_IsKeyboardFocusWithinChanged( object sender, DependencyPropertyChangedEventArgs e )
{ {
if( !( bool )e.NewValue ) if( ( bool )e.NewValue )
{
// Save the current value when focus is gained so we can restore it
// if the user enters an out-of-range value with ClipValueToMinMax=false.
_initialValueOnFocus = this.Value;
}
else
{ {
this.CommitInput(); this.CommitInput();
} }
@ -862,6 +869,14 @@ RoutedPropertyChangedEventHandler<object> ), typeof( UpDownBase<T> ) );
// From the UI, just allow any input. // From the UI, just allow any input.
if( !_isTextChangedFromUI ) if( !_isTextChangedFromUI )
{ {
// If ClipValueToMinMax is disabled, restore the original value
// when the user enters an out-of-range value, instead of
// silently truncating digits to fit the range.
if( !this.ClipValueToMinMax )
{
this.SetValueInternal( _initialValueOnFocus );
}
// This call may throw an exception. // This call may throw an exception.
// See RaiseInputValidationError() implementation. // See RaiseInputValidationError() implementation.
this.RaiseInputValidationError( e ); this.RaiseInputValidationError( e );

Loading…
Cancel
Save