Daniel Hoelbling-Inzko talks about programming
I’ve spent the better part of my weekend finding this bug and thought I’d share it in case someone else is having the problem. I’m building a WPF user interface with a NServiceBus backend and started noticing that sometimes changing data on the client didn’t generate UPDATE statements in my Database. I first assumed it had to do with my backend code, then I started digging through the various libraries I am using (NHibernate and NServiceBus) to find the problem.
After 2 days debugging through the backend code I finally found out that it’s the WPF application that sometimes sent wrong data. The scenario is quite simple:
This very simple dialog uses a StringFormat to display the Price field. This prevents me from using any other binding than a UpdateSourceTrigger=”OnLostFocus” because otherwise it would reformat the field on every key-press. Rendering it unusable due to a jumping focus caret.
The issue was that upon hitting Save, sometimes the Save method was executed before the data was bound to the model, sometimes the other way around. I genuinely thought I had a race condition until I noticed one little thing: Since it’s a decimal field I usually fill those in by using the number pad. That also led to me hitting the Enter quite often without thinking about it, thus invoking the Save method while still having the focus on the Price Textbox.
If you set a Button to IsDefault=”True” and hit Enter the Command will be executed without triggering the OnLostFocus Databindings in your Textbox, making your code act on stale model data. The only way around this is to either use UpdateSourceTrigger=”OnPropertyChanged” (not always applicable) or remove the IsDefault attribute from your form.
I still believe this is a bug in WPF, but at least now I know about it and can avoid it.