Wpf 验证错误时取消文本框输入

Wpf 验证错误时取消文本框输入,wpf,validation,textbox,Wpf,Validation,Textbox,当输入字符串无效时,文本框中的标准行为是显示一个红方块(例如,用户在数字文本框中引入一个字母)。当文本框失去焦点时会发生这种情况 我希望实现此行为: 文本框失去焦点 文本框进行内部验证(日期、数字等) 若输入的用户字符串无效,则恢复旧值,TextBox不会显示任何错误 此链接中的文本框中有一个验证示例: ! 公共类NameValidator:ValidationRule { 公共覆盖验证结果验证 (对象值,System.Globalization.CultureInfo CultureInf

当输入字符串无效时,文本框中的标准行为是显示一个红方块(例如,用户在数字文本框中引入一个字母)。当文本框失去焦点时会发生这种情况

我希望实现此行为:

  • 文本框失去焦点
  • 文本框进行内部验证(日期、数字等)
  • 若输入的用户字符串无效,则恢复旧值,TextBox不会显示任何错误

此链接中的文本框中有一个验证示例:


!
公共类NameValidator:ValidationRule
{
公共覆盖验证结果验证
(对象值,System.Globalization.CultureInfo CultureInfo)
{
如果(值==null)
返回新的ValidationResult(false,“值不能为空”);
其他的
{
if(value.ToString().Length>3)
返回新的ValidationResult
(false,“名称长度不能超过3个字符。”);
}
返回ValidationResult.ValidResult;
}
}

如果使用MVVM,恢复到旧值非常容易。在ViewModel的prop setter中,如果新值无效,则不能将其设置为模型,而是调用
PropertyChanged
。这将告诉绑定视图元素调用属性getter,它将返回旧值,从而将视图元素的内容恢复为旧值

示例(验证用户输入是否为
int
值):


这对于viewmodel中的验证非常有效。这里的问题是当用户引入无效的日期字符串,并且ViewModel中的属性是DateTime时。文本框本身进行内部验证并显示错误;textbox不会绑定到viewmodel,因为它无法将字符串转换为DateTime,并且错误的日期字符串仍保留在其中。
<ControlTemplate x:Key="validationErrorTemplate">
    <DockPanel>
        <TextBlock Foreground="Red" 
            DockPanel.Dock="Top">!</TextBlock>
        <AdornedElementPlaceholder 
           x:Name="ErrorAdorner"
        ></AdornedElementPlaceholder>
    </DockPanel>
</ControlTemplate> 




 public class NameValidator : ValidationRule
    {
        public override ValidationResult Validate
          (object value, System.Globalization.CultureInfo cultureInfo)
        {
            if (value == null)
                return new ValidationResult(false, "value cannot be empty.");
            else
            {
                if (value.ToString().Length > 3)
                    return new ValidationResult
                    (false, "Name cannot be more than 3 characters long.");
            }
            return ValidationResult.ValidResult;
        }
    }


<TextBox Height="23" HorizontalAlignment="Left" 
              Grid.Column="1" Grid.Row="0" Name="textBox1" 
              VerticalAlignment="Top" Width="120" 
              Validation.ErrorTemplate="{StaticResource validationErrorTemplate}"
         >
    <TextBox.Text>
        <Binding Path="Name" Mode="TwoWay" 
        UpdateSourceTrigger="LostFocus">
            <Binding.ValidationRules>
                <local:NameValidator></local:NameValidator>
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox> 
public string Number
{
    get { return _model.Number.ToString(); }
    set
    {
        if (_model.Number.ToString() != value)
        {
            int number;
            if (int.TryParse(value, out number))
            {
                _model.Number = number;
            }

            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Number));
        }
    }
}