1

In my class I've a Number property

double number;
public double Number { get => number; set { number = value; OnPropertyChanged(); } }

bound to a TextBox in xaml this way:

<TextBox Text="{Binding Number, UpdateSourceTrigger=PropertyChanged, StringFormat=N2}"/>

When I launch the app, the TextBox gets 0.00 automatically, probably because the value types are initialized by default. If I TAB to give TextBox focus, it doesn't select the 0.00 so I'have to manually delete the first 0, before the decimal point, there to enter some value. If I type an integer, I get the trailing .00 as expected BUT if I press . in numeric keypad to add some decimal points after the integer part, I get a red adorner around the TextBox and the .00 doesn't get deleted! So instead of pressing . and typing digits, I've to press to get to the decimal part first and type digits afterwards.

I want the TextBox to be blank/null when the app launches and when I hit . I want the trailing .00 to be replaced with whatever I type, ie. .25, thereafter If I press a button, to process the value in code, I want the TextBox to be blank/null again! How to do that?

Is there any masked TextBox to serve the purpose?

  • 2
    Oh, this is a very old problem with binding doubles. You might have to make a custom converter. – TripleAccretion Oct 22 '19 at 05:33
  • @ArtemK, lol, who knows how long will such an old problem be unresolved! Feels like I've to do two things: 1) an `InvokeCommand` to accept only digits and a single `.` and 2) a value converter to return a string with String.Format()! It's complicated, who knows which order `InvokeCommand` and `IValueConverter` will be called in, it'd be easier if the `InvokeCommand` gets the call first always. –  Oct 22 '19 at 06:38
  • 1
    This is one of the times I'd use a behaviour. You are causing this problem by making the binding transfer it's values every time the user presses a key. Remove UpdateSourceTrigger=PropertyChanged, and the default behaviour of a textbox is to transfer value on lostfocus so you can type and correct as much as you like until you tab away. – Andy Oct 22 '19 at 07:06
  • @Andy, oh! actually you're right, that updatetrigger making things complicated! I thought MS excel does that in real time with Accounting format BUT it actually doesn't, it reformats only after the cell loses focus. Which behaviour would you use in this case? In blend I've found 22 in total! –  Oct 22 '19 at 07:42
  • 1
    @EmonHaque I think he's talking about a custom Behavior, formerly in Windows.Interactivity, now in a standalone package. Just google WPF behaviors. – TripleAccretion Oct 22 '19 at 09:18
  • 1
    Yes, custom. I have two pieces of code I use for this. A validator and a behaviour. Both take parameters set things like number of decimal places, min and max. This looks like one of the things I use. https://stackoverflow.com/questions/16914224/wpf-textbox-to-enter-decimal-values/21307698 behaviors are nuget https://www.nuget.org/packages/Microsoft.Xaml.Behaviors.Wpf/ – Andy Oct 22 '19 at 11:28
  • 1
    @EmonHaque: A `double` is a value type that can never be `null`. If you want the `TextBlock` to be blank, you should bind to a `Nullable` which has a default value of `null`. – mm8 Oct 22 '19 at 13:46
  • @mm8, that's great, it solves half of the problem and if one gets used to press `right arrow` instead of `.` for values after decimal point, it actually solves the whole problm. Is there any chance of getting unexpected value like [this](https://stackoverflow.com/questions/8183922/binding-to-a-double-with-stringformat-on-a-textbox?rq=1) with `Nullable`? –  Oct 22 '19 at 22:43

1 Answers1

0

A double is a value type that can never be null. If you want the TextBlock to be blank, you should bind to a Nullable<double> which has a default value of null.

@mm8, that's great, it solves half of the problem and if one gets used to press right arrow instead of . for values after decimal point, it actually solves the whole problm. Is there any chance of getting unexpected value like this with Nullable<double>?

No, a Nullable<double> property can only be set to a double value or null. Nothing else. In other words, it accepts the exact same values as a double plus null (default(double?).

mm8
  • 163,881
  • 10
  • 57
  • 88