【问题标题】:IDataErrorInfo/WPF Binding - Validation over many ViewModelsIDataErrorInfo/WPF 绑定 - 对许多 ViewModel 进行验证
【发布时间】:2011-12-30 12:38:06
【问题描述】:

我正在尝试找到一种简单的方法来验证 ViewModel 的集合,使用 IDataErrorInfo 接口。

我有一个 ListBox,它绑定到 ViewModel 的 ObservableCollection。

  • 1 类“DataView<VMUser>”与ObservableCollection<VMUser>
  • 1 ViewModel 类“VMUser

如果我将 IDataErrorInfo 实现到我的 ViewModel 中,我可以验证例如 Age > 21 等等...但我无法验证是否没有其他用户使用相同的电子邮件,因为 ViewModel 没有彼此什么都不知道。

我没有找到强制我的 VMUser-DataTemplate 中的绑定使用 DataView 类的 IDataErrorInfo 的方法。 (不点击 OK 按钮...)

【问题讨论】:

    标签: wpf xaml data-binding binding


    【解决方案1】:

    对于基于业务规则的验证,我通常会公开一个我的 ViewModel 可以设置的验证委托。

    例如,包含您的集合的 ViewModel 可能如下所示:

    public ParentViewModel()
    {
        foreach(var user in UserCollection)
            user.AddValidationErrorDelegate(ValidateUser);
    }
    
    private string ValidateUser(object sender, string propertyName)
    {
        if (propertyName == "Email")
        {
            var user = (UserVM)sender;
    
            if (UserCollection.Count(p => p.Email== user.Email) > 1)
                return "Another user already has this Email Address";
        }
        return null;
    }
    

    这个想法是您的Model 应该只包含原始数据,因此它应该只验证原始数据。这可以包括验证最大长度、必填字段和允许的字符等内容。包含业务规则的业务逻辑应在ViewModel 中进行验证,这样就可以实现。

    IDataErrorInfoUserVM 类上的实际实现如下所示:

    #region IDataErrorInfo & Validation Members
    
    /// <summary>
    /// List of Property Names that should be validated
    /// </summary>
    protected List<string> ValidatedProperties = new List<string>();
    
    #region Validation Delegate
    
    public delegate string ValidationErrorDelegate(object sender, string propertyName);
    
    private List<ValidationErrorDelegate> _validationDelegates = new List<ValidationErrorDelegate>();
    
    public void AddValidationErrorDelegate(ValidationErrorDelegate func)
    {
        _validationDelegates.Add(func);
    }
    
    #endregion // Validation Delegate
    
    #region IDataErrorInfo for binding errors
    
    string IDataErrorInfo.Error { get { return null; } }
    
    string IDataErrorInfo.this[string propertyName]
    {
        get { return this.GetValidationError(propertyName); }
    }
    
    public string GetValidationError(string propertyName)
    {
        // If user specified properties to validate, check to see if this one exists in the list
        if (ValidatedProperties.IndexOf(propertyName) < 0)
        {
            //Debug.Fail("Unexpected property being validated on " + this.GetType().ToString() + ": " + propertyName);
            return null;
        }
    
        string s = null;
    
        // If user specified a Validation method to use, Validate property
        if (_validationDelegates.Count > 0)
        {
            foreach (ValidationErrorDelegate func in _validationDelegates)
            {
                s = func(this, propertyName);
                if (s != null)
                {
                    return s;
                }
            }
        }
    
        return s;
    }
    
    #endregion // IDataErrorInfo for binding errors
    
    #region IsValid Property
    
    public bool IsValid
    {
        get
        {
            return (GetValidationError() == null);
        }
    }
    
    public string GetValidationError()
    {
        string error = null;
    
        if (ValidatedProperties != null)
        {
            foreach (string s in ValidatedProperties)
            {
                error = GetValidationError(s);
                if (error != null)
                {
                    return error;
                }
            }
        }
    
        return error;
    }
    
    #endregion // IsValid Property
    
    #endregion // IDataErrorInfo & Validation Members
    

    【讨论】:

    • 我喜欢@Rachel 在这里采用的方法。我一直在使用 IDataErrorInfo.this[] 从模型中公开范围错误,但只有在用户单击确定后,我才会运行业务规则检查。很高兴能够使用这样的方法将业务规则错误暴露给 UI用户完成填写表单的其余部分并单击“确定”之前。
    • 这正是我想要的!在填写表格时通过 IDataErrorInfo 执行“更高级别”检查的一种非常好且简单的方法。 :)
    猜你喜欢
    • 2014-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-13
    • 1970-01-01
    • 1970-01-01
    • 2011-05-20
    相关资源
    最近更新 更多