I have the following WPF Textbox with input validation. Now the "problem" is, that the validation is not just optical, but a wrong value does not get written into the binded string. But, i want exactly that. The validation is supposed to be just optical.
Is there any practical way to achieve that with this setup? Thanks in advance for any advice!
<TextBox Width="60"
Height="20"
Style="{StaticResource TextBoxInError}"
Validation.ErrorTemplate="{StaticResource ValidationTemplate}">
<TextBox.Text>
<Binding Mode="TwoWay"
Path="BindingString"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<val:IsRealNumberRule />
<val:IsInDegreeNumberRangeRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
Resources:
<Style x:Key="TextBoxInError" TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}" />
<Setter Property="Background" Value="LightCoral" />
</Trigger>
</Style.Triggers>
</Style>
<ControlTemplate x:Key="ValidationTemplate">
<DockPanel>
<TextBlock
Margin="2"
FontWeight="Bold"
Foreground="Red">
!
</TextBlock>
<AdornedElementPlaceholder />
</DockPanel>
</ControlTemplate>
It is bound to this in the code behind:
private string _BindingString= "";
public string BindingString
{
get { return _BindingString; }
set
{
if (value == _BindingString)
{
return;
}
_BindingString= value;
RaisePropertyChanged("BindingString");
}
}
The input validation rules look like this:
public class IsInDegreeNumberRangeRule : ValidationRule
{
private const int _MinDegree = 0;
private const int _MaxDegree = 360;
public IsInDegreeNumberRangeRule()
{
}
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
int laneCount = 0;
try
{
if (((string)value).Length > 0)
laneCount = Int32.Parse((String)value);
else
return ValidationResult.ValidResult;
}
catch (Exception e)
{
return new ValidationResult(false, e.Message);
}
if ((laneCount < _MinDegree) || (laneCount > _MaxDegree))
{
return new ValidationResult(false, $"Please input value between {_MinDegree}° and {_MaxDegree}° .");
}
return ValidationResult.ValidResult;
}
}
Now the "problem" is, that the validation is not just optical, but a wrong value does not get written into the binded string. But, i want exactly that. The validation is supposed to be just optical.
Is there any practical way to achieve that with this setup? Thanks in advance for any advice!
CodePudding user response:
You can run the validation rule after the source property has been updated by setting the ValidationStep property to UpdatedValue:
<Binding.ValidationRules>
<val:IsRealNumberRule ValidationStep="UpdatedValue" />
<val:IsInDegreeNumberRangeRule ValidationStep="UpdatedValue" />
</Binding.ValidationRules>
