在WPF中构建错误摘要

时间:2013-05-15 17:51:45

标签: wpf xaml

我的表单绑定到一个实现IDataErrorInfo的对象,并且它在逐个字段的基础上正确验证。我想基于表单上的字段而不是Error的{​​{1}}属性来总结结果。有没有办法可以以某种方式循环控制并确定哪些控件无效?

谢谢!

2 个答案:

答案 0 :(得分:0)

要执行此MVVM方式,您必须首先收集ViewModel中的所有错误。也就是说,找到所有属性都被验证为false,然后将所有这些属性的错误文本添加到集合/列表/数组,然后使用此集合/列表/数组在UI上显示错误摘要中的错误。

答案 1 :(得分:0)

以下是我的建议,但我不太清楚你的意思是“根据表格上的字段总结结果”。我认为我所建议的应该允许你做任何你想做的事。

我建议您使用IDataErrorInfo并使用您的对象及其字段而不是特定控件。在我所有ViewModel(你正在显示的数据)的基类中,我实现了像这样的IDataErrorInfo

private Dictionary<string, string> errors = new Dictionary<string, string>();

public virtual string Error
{
    get { return String.Join(Environment.NewLine, errors); }
}

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

public string this[string propertyName]
{
    get
    {
        string result;
        errors.TryGetValue(propertyName, out result);
        return result;
    }
}

protected void SetError<T>(Expression<Func<T>> prop, String error)
{
    String propertyName = PropertySupport.ExtractPropertyName(prop);

    if (error == null)
        errors.Remove(propertyName);
    else
        errors[propertyName] = error;

    OnHasErrorsChanged();
}

protected string GetError<T>(Expression<Func<T>> prop, String error)
{
    String propertyName = PropertySupport.ExtractPropertyName(prop);

    String s;
    errors.TryGetValue(propertyName, out s);
    return s;
}

protected virtual void OnHasErrorsChanged()
{

}

然后,我可以实现这样的属性,用于数据绑定以存储验证错误:

public String ProjectName
{
    get { return projectName; }
    set
    {
        if (value != projectName)
        {
            projectName = value;
            SetError(() => ProjectName, ValidateProjectName());
            RaisePropertyChanged(() => this.ProjectName);
        }
    }
}

获取任何字段错误

String error = GetError( () => SomeField ); // OR
String error = this["SomeField"];

或者您可以使用错误来获取所有错误的列表


注意在这个例子中,我使用的是我实现的SetError和 RaisePropertyChanged ,它是在Prism的 NotificationObject 类中实现的。 NotificationObject 类只是实现了 INotifyPropertyChanged ,并为您提供了一个名为RaisePropertyChanged的PropertyChanged(“PropertyName”)的重构安全版本,我传递了lamda表达式。

如果你不使用Prism,你可以简单地让SetError取两个字符串(属性,错误)。或者,自己实现PropertySupport.ExtractPropertyName方法以使用此重构安全版本。

e.g。

public static class PropertySupport
{
    public static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpresssion)
    {
        if (propertyExpresssion == null)
        {
            throw new ArgumentNullException("propertyExpression");
        }

        var memberExpression = propertyExpresssion.Body as MemberExpression;
        if (memberExpression == null)
        {
            throw new ArgumentException("The expression is not a member access expression.", "propertyExpression");
        }

        var property = memberExpression.Member as PropertyInfo;
        if (property == null)
        {
            throw new ArgumentException("The member access expression does not access a property.", "propertyExpression");
        }

        var getMethod = property.GetGetMethod(true);
        if (getMethod.IsStatic)
        {
            throw new ArgumentException("The referenced property is a static property.", "propertyExpression");
        }

        return memberExpression.Member.Name;
    }
}