Stack OverFlow 与自定义验证器

Stack OverFlow with Custom validator

我已经实现了如下自定义验证器...

 public class RquiredFiledValidation:ValidationRule
{
    public string ErrorMessage { get; set; }

    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        if (string.IsNullOrWhiteSpace(value.ToString()))
            return new ValidationResult(false, ErrorMessage);
        else
            return new ValidationResult(true, null);
    }
}

并附上如下文本框...

 <TextBox x:Name="txtLoging" Grid.Column="1" HorizontalAlignment="Stretch" Validation.ErrorTemplate="{x:Null}" VerticalAlignment="Center"  Margin="0,40,30,0">
        <Binding Path="Text" ElementName="txtLoging" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">
            <Binding.ValidationRules>
                <Validate:RquiredFiledValidation  ErrorMessage="Please Provide Login Name"></Validate:RquiredFiledValidation>
            </Binding.ValidationRules>
        </Binding>
    </TextBox>

我的问题是...

1) 当我直接点击登录按钮时,验证没有被触发

2) 当我在文本框中输入一个字符时,验证被触发但产生堆栈溢出错误。

I have solve the first problem from code behind as below txtLoging.GetBindingExpression(TextBox.TextProperty).UpdateS‌​ource(); txtPassword.GetBindingExpression(Infrastructure.AttachedProp‌​erty.PasswordAssiste‌​nt.PasswordValue).Up‌​dateSource(); But how solve the same in MVVM

如果您关心 MVVM 模式,则不应使用验证规则来验证您的数据。验证规则属于视图,在 MVVM 应用程序中,验证逻辑应在视图模型或模型中实现 class.

你应该做的是实现 INotifyDataErrorInfo 接口:https://msdn.microsoft.com/en-us/library/system.componentmodel.inotifydataerrorinfo%28v=vs.110%29.aspx

给你举个例子:

public class ViewModel : INotifyDataErrorInfo
{
    private string _username;
    public string Username
    {
        get { return _username; }
        set
        {
            _username = value;
            ValidateUsername();
        }
    }

    private void ValidateUsername()
    {
        if (_username == "valid")
        {
            if (_validationErrors.ContainsKey("Username"))
                _validationErrors.Remove(nameof(Username));
        }
        else if (!_validationErrors.ContainsKey("Username"))
        {
            _validationErrors.Add("Username", new List<string> { "Invalid username" });
        }

        RaiseErrorsChanged("Username");
    }


    private readonly Dictionary<string, ICollection<string>>
        _validationErrors = new Dictionary<string, ICollection<string>>();

    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
    private void RaiseErrorsChanged(string propertyName)
    {
        if (ErrorsChanged != null)
            ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
    }

    public System.Collections.IEnumerable GetErrors(string propertyName)
    {
        if (string.IsNullOrEmpty(propertyName)
            || !_validationErrors.ContainsKey(propertyName))
            return null;

        return _validationErrors[propertyName];
    }

    public bool HasErrors
    {
        get { return _validationErrors.Count > 0; }
    }
}

<TextBox Text="{Binding Username, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True}" />

请参阅以下博客 post 以获取有关 WPF 中数据验证工作原理的概况以及有关如何实现它的一些综合示例的详细信息。

WPF 中的数据验证: https://blog.magnusmontin.net/2013/08/26/data-validation-in-wpf/