Describe the bug
NumberBox always defaults to showing "0" if a value isn't explicitly set.
Steps to reproduce the bug
Expected behavior
NumberBox should show PlaceholderText instead of "0" by default if no value is explicitly set.
Actually it should probably never default to 0 and should just stay unset/null? Defaulting to 0 a) could unintentionally set data model values that the app author and end-user didn't intend, and b) could prevent input validation from highlighting the fact that a user needs to explicitly set a value in a form.
Defaulting to null would mean you get PlaceholderText when set, and blank when no placeholder is set.
Screenshots
Version Info
NuGet package version:
Microsoft.UI.Xaml 2.3.191129002
| Windows 10 version | Saw the problem? |
| :--------------------------------- | :-------------------- |
| Insider Build (xxxxx) | |
| May 2019 Update (18362) | Yes |
| October 2018 Update (17763) | |
| April 2018 Update (17134) | |
| Fall Creators Update (16299) | |
| Creators Update (15063) | |
| Device form factor | Saw the problem? |
| :-------------------- | :------------------- |
| Desktop | Yes |
| Mobile | |
| Xbox | |
| Surface Hub | |
| IoT | |
Additional context
The default value should probably be double.NaN. When the value is double.NaN, Text should be an empty string and any PlaceholderText should be shown.
When a Minimum
is set I think it would be better to default to the Minimum
, since the expectation is that if we set a Minimum
, the value does not fall below that, which might happen if we default to 0.
See this issue over at XCG where this is actually a problem.
Even with Minimum
set it's probably still useful to have a value for "not set" (e.g. NaN) so we can show the placeholder text.
Defaulting directly to Minimum
could prevent useful placeholder text from being shown, and could cause values to erroneously get set and validated (e.g. via databinding to a model) when the user didn't actually enter anything.
If a value is required and hasn't been entered then an error seems correct.
I think the control should default to no value and show the placeholder text. That has special meaning that a user has not made a selection. If a developer wants the minimum this is very easy to set in code -- it is not so easy to determine a user hasn't made a selection.
That said, I no longer think we should be using double.NaN. The backing value type should be "double?" and the default null. This would fix the binding issues in #1721.
@SavoySchuler can you weight in on the right fix?
Maybe enforcing Minimum
as default is not the best solution. However if we enable the default to be null, would there be any way to force users to input a value? Or would this be something the developer has to deal with (e.g. null checks)?
@chingucoding Data validation is coming to WinUI 3.0. Perhaps that would be the best way to inform the user they need to make a selection. I would leave it up to the business logic to replace null with the minimum value when necessary so the view model can retain the 'no selection made' information.
Also note that CalendarDatePicker
supports null/no-selection while DatePicker
does not. So the platform doesn't seem to be consistent here either. In my own experience supporting null/no-selection is always best and the application developer can override that in the view model or business logic as required.
@chingucoding Data validation is coming to WinUI 3.0. Perhaps that would be the best way to inform the user they need to make a selection. I would leave it up to the business logic to replace null with the minimum value when necessary so the view model can retain the 'no selection made' information.
That would probably fix this, however I am not quite sure how easy it will be to use them that is, how much effort it is to simply filter for null/non null.
Also note that
CalendarDatePicker
supports null/no-selection whileDatePicker
does not. So the platform doesn't seem to be consistent here either. In my own experience supporting null/no-selection is always best and the application developer can override that in the view model or business logic as required.
It's surprising that those behave differently. Maybe there could also be a flag for input controls such as NumberBox and CalendarDatePicker that would specify whether null is accepted as value or if there is a default and the user can pick a new value if they want.
Since it hasn't been mentioned yet, Minimum isn't appropriate for symmetric inputs (e.g. -100 to +100). If a hard coded default has to be used, using the minimum _absolute_ value is usually more appropriate, but at that point the default selection gets suspiciously "smart" which makes me think having a hard coded default is not right in the first place.
Taking @weltkante s argument into account, it probably would be the best to have a property "DefaultValue" which can be set to:
This would allow developers to force a NumberBox to have a valid value (and not have the app crashing because the NumberBox changed to a non valid value as fallback) but also would allow the NumberBox to show a PlaceHolder when the user has not entered text or has cleared the NumberBox.
It seems like that NaN is now the default value, which would fix this issue.
@chingucoding NaN was the originally intended value to specify a value has not been set, so if that is now the default this now functions as planned and the placeholder text should be visible.
The problem everyone missed that I'm also trying to address here is that object.Equals(double.NaN, double.NaN) returns false per IEEE specification. This then leads to a stack overflow exception when using two-way binding #1721. If we have double.NaN anywhere in the control I think binding will break.
For this reason there was the EmptyValue
value suggest by @sonnemaf that is equivalent to your DefaultValue
suggestion. However, I really don't want to rely on new concepts in the platform to fix this. Object.Equals(null, null) returns true in the platform. For this reason null should be the default empty value of the NumberBox and the type changed to double?
I've added this to the requested agenda for the next community call. There are some fundamental design concepts to agree on regarding consistency with default values.
Thanks for the all the info to work with everyone! And sorry for the delayed response - it was a long weekend for me. 馃槄
I'll need to revisit this with @teaP and @MikeHillberg. I believe there were some compatibility restrictions that prevented setting default to any non-numerical value, but I will double check.
As per the Guidelines, PlaceholderText is (currently) displayed only when Value is set to NaN or when the input is cleared by the user.
Most helpful comment
@SavoySchuler can you weight in on the right fix?