inotifydataerrorinfo获取所有验证错误

时间:2015-11-20 17:02:49

标签: c# wpf mvvm

目前我正在开发.net 4.5 wpf MVVM应用程序,其验证系统由INotifyDataErrorInfo处理。在应用程序的某个时刻,我必须检查是否有任何验证错误,目前它是这样做的:

public class RootViewModel : BindableBase
{
     //class code

            if (designInformation.Technology == Technology.CVT)
            {
                if (designInformation.HasErrors) return;
                if (InfoInputViewModel.TrafoProperties.HasErrors) return;
                if (InfoInputViewModel.CapacitorVoltageTransformerViewModel.CapacitorVoltageDivider.HasErrors) return;
                if (InfoInputViewModel.CapacitorVoltageTransformerViewModel.IntermediateVoltageTransformer.HasErrors) return;
                if (SpecialDesignViewModel.SpecialDesignInformation.HasErrors) return;
                foreach (var item in InfoInputViewModel.SecondaryWindings.WindingsCollection)
                {
                    if (item.HasErrors) return;
                }

                performCalculationsCVT();
            }
}

我正在寻找一种方法来通过立即从模型中获取所有错误来简化此代码,但不知道从哪里开始解决此问题。

Bellow是我使用的INotifyDataErrorInfo接口的实现。

public class ValidableBase : BindableBase, INotifyDataErrorInfo
{
    protected readonly Dictionary<string, ICollection<string>>
    _validationErrors = new Dictionary<string, ICollection<string>>();

    #region INotifyDataErrorInfo Implementation

    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

    protected void RaiseErrorsChanged(string propertyName)
    {
        if (ErrorsChanged != null)
            ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
    }

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

        return _validationErrors[propertyName];
    }

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

    public void AddError(string propertyName, string message)
    {
        if (_validationErrors.ContainsKey(propertyName))
        {
            string value = _validationErrors[propertyName].First();
            value += Environment.NewLine;
            value += message;
            _validationErrors[propertyName] = new List<string> { value };
        }
        else
            _validationErrors[propertyName] = new List<string> { message };

        RaiseErrorsChanged(propertyName);
    }

    public void RemoveError(string propertyName)
    {
        _validationErrors.Remove(propertyName);

        RaiseErrorsChanged(propertyName);
    }

    [XmlIgnore]
    public Dictionary<string, ICollection<string>> ValidationErrors 
    {
        get { return this._validationErrors; }
    }

    #endregion 
}

}

1 个答案:

答案 0 :(得分:1)

显然,基类不知道特定子类具有哪些属性,更不用说实现INDEI了。您必须编写逻辑来执行此操作。有很多方法可以实现这一目标。

对我而言,我将基本类添加一个抽象方法

abstract class ValidableBase 
{
    // snip
    protected abstract IEnumerable<ValidableBase> GetValidableProperties();
    // snip

然后更改HasErrors以递归方式调用HasErrors上述调用的结果

public bool HasErrors
{
    get { return _validationErrors.Count > 0 ||
          GetValidableProperties().Any(x => x.HasErrors); }
}

GetValidableProperties的示例实现可能是

protected override IEnumerable<ValidableBase> GetValidableProperties()
{
    yield return SomeProperty; // a Validable property
    yield return SomeOtherProperty; // this too
    foreach(var prop in SomeCollectionProperty) // collection of Validable
        yield return prop;
}

最后,我将Validable重命名为Validatable,这是正确的(英语)拼写。如果我是西班牙语或法语,我可能会跳过最后一步。