使用自定义验证器堆栈OverFlow

时间:2016-12-22 06:29:35

标签: c# wpf customvalidator

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

 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)当我在文本框中放置一个字符时,验证会被触发,但会产生堆栈溢出错误。

1 个答案:

答案 0 :(得分:1)

  

我已经解决了代码背后的第一个问题,如下面的txtLoging.GetBindingExpression(TextBox.TextProperty).UpdateS ource(); txtPassword.GetBindingExpression(Infrastructure.AttachedProp erty.PasswordAssiste nt.PasswordValue).UP dateSource();但是如何在MVVM中解决相同的问题

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

您应该做的是实现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}" />

有关WPF中数据验证工作原理以及如何实施数据的全面示例的详细信息,请参阅以下博客文章。

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