Reputation: 63
I have a textbox bound to a nullable decimal property.
<TextBox Text="{Binding DueRent}" Style="{x:Null}" Width="150"/>
public decimal? DueRent { get => _dueRent; set => _dueRent = value; }
When my TextBox is first displayed it contains Null and there is no error template shown. If I invalidate it, say by entering "aa" or "space" then I get the red border, Great. If I then enter a valid number say 23.7 the border goes away, again great. But, if I just delete the invalid text or the valid number, I get the red border, which is not great. I want the 'empty' text box not to display the red border. The value is not a required value but obviously, if it is entered then it needs to be valid. The validation is a bit more involved than just being a valid decimal but that is dealt with elsewhere.
It appears that the getter or setter is not called when an invalid entry is made, it just goes into error.
If I use a Validation.Template
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel>
<TextBlock DockPanel.Dock="Left" FontWeight="Bold" Foreground="Red">*</TextBlock>
<TextBlock DockPanel.Dock="Bottom" Foreground="Purple" Text="{Binding ErrorContent}" />
<Border BorderBrush="Red" BorderThickness="2">
<AdornedElementPlaceholder />
</Border>
</DockPanel>
</ControlTemplate>with the
</Setter.Value>
</Setter>
then the message displayed is 'Value aa cannot be converted', which makes sense in as much as 'aa' cannot be converted to a decimal, however, if I then put another invalid value into the box and tab away the error message does not change which suggests that it is not re-validating itself with the new invalid data?!?
I have tried FallBackValue = 0 and = x:Null.
I have tried a Binding.ValidationRules as found here How do I get a TextBox to only accept numeric input in WPF?
It returns IsValid=False when value is 'aa' with the correct error message and returns IsValid=True when the value Is '' but the textbox stays invalid with the new message 'Value '' cannot be converted' which it is not getting from the Binding.ValidationRules
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
var validationResult = new ValidationResult(true, null);
if (value != null )
{
if (!string.IsNullOrEmpty(value.ToString()))
{
var regex = new Regex("[^0-9.-]+"); //regex that matches disallowed text
var parsingOk = !regex.IsMatch(value.ToString());
if (!parsingOk)
{
validationResult = new ValidationResult(false, "Illegal Characters, Please Enter Numeric Value");
}
}
}
return validationResult;
}
How do I stop the TextBox going into Error when the TextBox is empty?
Thanks.
Upvotes: 0
Views: 718
Reputation: 28968
You can't bind TextBox.Text
to a non string
type and expect the TextBox
to behave special. It's not a numeric input control. As the name of the property Text
and its type indicates it is a string
input control.
That your binding to a non string
property type works is because the XAML engine uses type converters and tries to convert the value from string
to the correct type (in this case decimal
). Because there exists a default converter for a string
to decimal
conversion, you get no conversion errors if the string is numeric.
But the TextBox
still behaves like a text input field. While an empty string is a valid string
value it isn't convertible to a numeric value by default.
You must provide the correct conversion, for example convert an empty string
to 0
. Alternatively, intercept keyboard input to replace whitespace with 0
. This requires some extra logic e.g. to suppress multiple whitespace characters.
Attaching a converter for this single use case of suppressing an empty string input seems to be more convenient:
public class WhitespceToNumericValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
=> value;
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
=> value is string input && string.IsNullOrWhiteSpace(input)
? 0
: value;
}
<Window.Resources>
<WhitespceToNumericValueConverter x:Key="WhitespceToNumericValueConverter" />
</Window.Resources>
<TextBox Text="{Binding DueRent, Converter={StaticResoucre WhitespceToNumericValueConverter}}" />
Upvotes: 0