TextBox bound to Decimal with UpdateSourceTrigger=PropertyChanged
Asked Answered
S

2

11

I've been battling this issue for a while now and seem not to be able to come up with a concrete workaround - I have a TextBox which is bound to a decimal, and the binding has UpdateSourceTrigger set to PropertyChanged and is so by necessity (LostFocus won't work well in this case). The default behavior while I'm sure is somehow explainable, is not acceptable for my purposes, so I've tried the following StringFormat, which I had thought remedied the issue, but only partially and am now looking for something more concrete. My originaly fix was to add a string format to the binding...in my case it was

StringFormat={0:#.#####} 

so when typing something like .12345 or 1.5 the solution works great, however if I type .01234, as soon as I hit the zero key, it removes the decimal I had just typed...which for obvious reasons would be disasterous in terms of data entry. I'm hoping that my familiarity with string formatting is just lacking. Wost case scenario I'll have my exposed property be a string and the setter and getter just convert to decimal, but that seems like a hacky solution.

Thanks!

Aj

Schaffner answered 27/4, 2012 at 16:10 Comment(4)
I feel your pain. I and (we, in various projects) ended up creating a NumericTextBox UserControl that was able to handle the situation you describe as well, as other interesting inputs: int vs double, handling negative values, decimals, validation (numeric vs alpha) etc. Depending on how robust your textbox has to be, I would recommend creating your own NumericTextBox that inherits from TextBox and add your rules. Good luck!Zollie
@denismorozov - while I didn't come up with a legit solution, I did read another article where someone suggested setting FocusManager.IsFocusScope="False" on the button to take focus away from the textbox, which in my case allows me to switch from using property changed back to the default of lost focus because it will execute my binding prior to the button's command execution. It may not be a solution for you, but it worked for me at least in this instance.Schaffner
hmm, interesting, I will try that!Zollie
@denismorozov - an addition to that, if you don't want your button to keep the focus after click, you can use the FocusManager.IsFocusScope in conjunction with FocusManager.FocusedElement and set it to a control that can receive focus...this way your button doesn't stay highlighted after click...also makes a nice way to move focus in other instances where it would be helpful.Schaffner
N
1

I came across this because Im seeing the same issue with a .Net 4.6.2 build. I needed to enter an exchange rate, e.g. 1.15 and found it was ending up as 115 with the decimal removed. My workaround was to bind to a string property that maintained it's own string value while input e.g. 1, 1., 1.1, 1.15. But with each input attempted to update the underlying numeric property inside a Try Catch. It's far from elegant, but works for my needs.

Neapolitan answered 2/7, 2018 at 19:42 Comment(0)
H
0

You have two simple choices to achieve what you want:

  1. Try typing a '0' first... you can enter '0.01234' without issue.

  2. Use StringFormat={}{0:0.00000} instead... then you can enter '.01234' without issue.

Horrify answered 31/7, 2013 at 8:15 Comment(10)
Thank you for your response - it's been quite a while since we finished the associated application where we were having this problem. That being said, for number 1 in your suggested solution, expecting a user to consistently type a zero first is not realistic, especially knowing that it'll really botch up the number if they forget. The second suggestion you posted would be fine, but if recollection serves (it's been a while), this did not work either on .Net 3.5 (same problem) - might have changed in subsequent versions...but we couldn't get this to work at the time.Schaffner
Please add an answer with your solution and mark it as the correct answer if you have one. People may continue to provide answers until you do.Horrify
There wasn't one, which is why it's still open...pretty sure it was a bug in .Net 3.5 that they never really thought through nor repaired...if someone has a solution that works, I'd love to hear it as it's something that plagued me for months.Schaffner
I just gave you a solution that works... I just tested it with .NET 3.5 too and it works just fine still. Try it yourself. Otherwise, what kind of magical solution are you still waiting for?Horrify
I tried your solution with the exact same results...what build of. Net 3.5 are you on? Please post your XAML and CS file where you got this to work consistently. Our setup was MVVM, bound property in the VM that was getting/setting a decimal, making sure to set the update source trigger to property changed. If you tested that and got it to work, I'd be very interested to see it since this plagued us and a lot of other people online when I researched this last year.Schaffner
I was initially running .NET 4.0. After seeing your question, I created a new WPF application and added a DependencyProperty of type decimal into MainWindow.xaml.cs. In MainWindow.xaml, I added a TextBox, bound the Text property to the DependencyProperty and set the StringFormat to {}{0:0.00000}. That worked fine, but you said it didn't in .NET 3.5, so I changed the target framework in the project properties to 3.5 and ran the program again without problem. Unfortunately, I butchered that project long ago testing code whilst trying to find answers to other people's questions.Horrify
P.S. Where do I find the build number?Horrify
The difference between the StringFormat {0:#.#####} and {}{0:0.00000} is that # could be any number, but 0 will add zeros by default. Therefore it will add the missing 0 from .01234 to produce 0.01234. I'm not sure, but you might even be able to mix them and use {}{0:0.#####}.Horrify
The build number can be found by looking in windows explorer where the .net framework is located (the folder name is the build number).Schaffner
I understand the difference between the string formats, and had tried both. The issue was specifically with the updatesourcetrigger being set to propertychanged - it as you typed tried to update the binding which messed things up...just a guess. In your test case, did you ensure you set the updatesourcetrigger to propertychanged? I've tried this several times with no luck even still.Schaffner

© 2022 - 2024 — McMap. All rights reserved.