DoubleEditBox.Value seems like single precision & unwanted behavior with Style.Triggers

Editors for WPF Forum

Posted 8 months ago by Tony Pulokas
Version: 17.1.0652
Platform: .NET 4.6
Environment: Windows 10 (64-bit)
Avatar

I am in the process of upgrading from WPF Studio version 2011.2 to 2017.1.  The goal is to upgrade to version 2019, but I’m upgrading in steps in order to limit how many breaking changes I have to deal with at one time.  I have found a couple problems dealing with the DoubleEditBox in version 2017, where things were working as expected in version 2011.  The problems seem related on a superficial level, but perhaps not related at a fundamental level.


In version 2011.2, my DoubleEditBox was assigned a Style that looks like this:


    <Style x:Key="DoubleEditBoxStyle" TargetType="editors:DoubleEditBox">
        <Setter Property="SpinnerVisibility" Value="Collapsed" />
        <!--Only display 8 digits when cursor is not on control.
            When keyboard-focused, display all digits-->
        <Setter Property="Format" Value="G8" />
        <Style.Triggers>
            <Trigger Property="IsKeyboardFocusWithin" Value="True">
                <Setter Property="Format" Value="R" />
            </Trigger>
        </Style.Triggers>
    </Style>

Where this is the XAML for the DoubleEditBox itself:


<editors:DoubleEditBox
                Style="{StaticResource DoubleEditBoxStyle}" Width="86"
                Value="{Binding CachedValues[Value], TargetNullValue=0, Mode=TwoWay}"
                IsReadOnly="{Binding IsReadOnly}" />

The Format was changing as expected, depending on whether the DoubleEditBox had keyboard focus.  When I typed the value “0.12345678901234567890123” into the DoubleEditBox, and set a breakpoint in the setter of the Binding source, I see a value of 0.12345678901234568, which seems like the decimal digits got cut off at about double precision like I’d expect.

With this same code in version 2017.1, I found that if I typed a new value into the DoubleEditBox, and then clicked off of the control, my new value would immediately revert to the previous value.  I set my breakpoint in the setter of the Binding source, but the breakpoint was not hit.  I found that if I instead typed in a new value, then hit the enter key instead of clicking off of the DoubleEditBox, the breakpoint in the setter of the Binding source was hit, and the new value would stick.  I gradually put the clues together to figure out that the Trigger in my Style (shown in the code sample above) was causing the problem.  My interpretation is that with version 2017.1, the Value of the DoubleEditBox is not processed until after the Trigger changed the Format, and the change to the Format caused the new value of the Value property to be lost.  Something about that chain of events was different in version 2011.2


I found I was able to get the desired effect with version 2017.1 by changing my Style like so:
    <Style x:Key="DoubleEditBoxStyle" TargetType="editors:DoubleEditBox">
        <Setter Property="SpinnerVisibility" Value="Collapsed" />
        <!--Only display 8 digits when cursor is not on control.
            When keyboard-focused, display all digits-->
        <Setter Property="Format" Value="G8" />
        <EventSetter Event="LostFocus" Handler="DoubleEditBox_LostFocus" />
        <EventSetter Event="GotFocus" Handler="DoubleEditBox_GotFocus" />
    </Style>

With these event handlers:
        public void DoubleEditBox_LostFocus(Object sender, RoutedEventArgs e)
        {
            var editBox = sender as DoubleEditBox;
            if (editBox == null) return;
            editBox.Format = "G8";
        }
        public void DoubleEditBox_GotFocus(Object sender, RoutedEventArgs e)
        {
            var editBox = sender as DoubleEditBox;
            if (editBox == null) return;
            editBox.Format = "R";
        }
By setting breakpoints in the event handlers, I can see that the Format value is changing as expected.  However, I was confused by the fact if I typed “0.12345678901234567890123” into the DoubleEditBox, this would change to “0.12345679” and stay there, regardless of whether the control had focus.  I set my breakpoint in the setter of the Binding source, and sure enough, the value being passed to the setter is “0.12345679”.  It seems to be cut off at single precision!  I experimentally changed the Format value from “G8” to “G4” in the Style and the event handlers, and now I could see the effect of the Format changing with focus.  However, the value “0.12345679” is still all that appears in the setter.  FWIW, if I comment out the EventSetters and change the Format to “G12”, the precision of the value gets cut off in exactly the same way.


So for problem number one, regarding the Trigger that changes the Format value, is there a different way I could handle this?  The Trigger felt like a preferred way to write the code, because it didn’t involve any code-behind.  Furthermore, I believe that any instance of the DoubleEditBox could override the Style if needed by assigning the Format value using a XAML attribute.  I don’t think the approach with the event handlers would have this flexibility.


Problem number two seems to be that my DoubleEditBox value always seems to turn into a single-precision value, regardless of the string format.  I looked for any property of the DoubleEditBox that might be affecting this, and couldn’t find anything.  Am I missing something?


Should I expect either of these issues to be fixed as I upgrade beyond version 2017.1?

[Modified 8 months ago]

Comments (2)

Answer - Posted 8 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Tony,

For the first problem, from debugging (in the 2019.1 version) I can see that the Format change from the Trigger change on IsKeyboardFocusedWithin="False" occurs before our own internal TextBox.LostKeyboardFocus event fires.  The format change updates the text from the current Value, but the text wasn't converted to a Value yet since LostKeyboardFocus didn't yet fire.  When you change to using the event trigger, it probably alters the sequence so your Format change occurs afterward.

We found that if we internally attach to the TextBox.IsFocusWithinChanged event instead of LostKeyboardFocus, we can get our lost-focus logic to execute before your trigger, and it seems to fix the problem.  This update will be in the next 2019.1 maintenance release.

For the second problem, we have a DoubleEditBox.RoundingDecimalPlace property that defaults 8.  it can be set to anything 0..15.  I believe that's what you're running into here.  With .NET 's Double-based numbers and their lack of exact precision, sometimes they don't end up rendering as expected (like a desired value of 8 might be 7.999999999999999999 as a random example).  That's why we found that 8 decimal places is a good place to do some rounding to make sure we get expected output.  But for scenarios where more precision is needed, you'd want to up that to 15.


Actipro Software Support

Posted 8 months ago by Tony Pulokas
Avatar

Thanks for the help!  I have now upgraded to version 2019 and I've found the DoubleEditBox.RoundingDecimalPlace property there.

The latest build of this product (v2020.1.0) was released 21 days ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.