.net WPF中的交叉属性验证

.net WPF中的交叉属性验证,.net,wpf,validation,mvvm,idataerrorinfo,.net,Wpf,Validation,Mvvm,Idataerrorinfo,目前,我正在使用IDataErrorInfo接口在WPF应用程序中实现验证。作为该接口一部分的索引器允许验证单个属性,如下所示: public string this[string columnName] { get { switch (columnName) { case "LastName": if (string.IsNullOrEmpty(this.LastName))

目前,我正在使用
IDataErrorInfo
接口在WPF应用程序中实现验证。作为该接口一部分的索引器允许验证单个属性,如下所示:

public string this[string columnName]
{
    get
    {
        switch (columnName)
        {
            case "LastName":
                if (string.IsNullOrEmpty(this.LastName))
                    return "LastName must not be empty.";
                break;
            // case, case, case, etc., etc.
        }
        return null;
    }
}
public string this[string columnName]
{
    get
    {
        switch (columnName)
        {
            case "ShippingDate":
            case "InvoiceDate":
                if (this.ShippingDate > this.InvoiceDate)
                    return "Invoice date must not be before shipping date.";
                break;
        }
        return null;
    }
}
如果发生验证错误,我会在文本框旁边显示一个带工具提示的星号

如果我有与单个属性不严格相关的验证规则,我该怎么办?例如,如果表示订单的域实体具有发货日期和发票日期,并且我希望验证发票日期必须晚于或等于发货日期的规则

当然,我也可以通过两次检查关系,一次检查columnName“ShippingDate”,一次检查columnName“InvoiceDate”,然后在UI的两个输入字段中用星号标记错误,将此规则强制输入到索引器中,如下所示:

public string this[string columnName]
{
    get
    {
        switch (columnName)
        {
            case "LastName":
                if (string.IsNullOrEmpty(this.LastName))
                    return "LastName must not be empty.";
                break;
            // case, case, case, etc., etc.
        }
        return null;
    }
}
public string this[string columnName]
{
    get
    {
        switch (columnName)
        {
            case "ShippingDate":
            case "InvoiceDate":
                if (this.ShippingDate > this.InvoiceDate)
                    return "Invoice date must not be before shipping date.";
                break;
        }
        return null;
    }
}
但我更希望独立于索引器进行“对象级别”或“跨属性”验证(索引器应仅报告无效的“单一属性状态”),并在UI上单独显示这些对象级别或关系错误

我希望
IDataErrorInfo
接口的
Error
属性可以用于对象级验证。例如,当我在文本框的绑定表达式中指定
validateSondaerRors=True
时,WPF调用索引器进行属性验证。但是,每当我更改输入字段中的某些数据时,我找不到一种方法来告诉WPF调用
Error
属性。也许我对这房子用途的猜测是错误的

如何在WPF中实现跨属性验证?


提前感谢您的建议

关于我的问题,我是否可以设置绑定,以便WPF自动测试
IDataErrorInfo
接口的
Error
属性,我发现以下否定答案:

有人问:

基本上,我想知道一个 将触发 IDataErrorInfo.错误的测试,在 验证数据错误的方法 导致测试 IDataErrorInfo.Item

Microsoft Online Community Support的答复:

设置ValidateSondaErrors 仅绑定类的属性 IDataErrorInfo.项目的测试和 不是IDataErrorInfo.Error的错误

绑定类不提供 属性来检查 IDataErrorInfo。错误为 ValidatesOnDaerRors属性到 到目前为止,请检查IDataErrorInfo.项目

为了得到你想要的,我们必须建立 数据绑定到 IDataError。错误

因此,
Error
属性没有比在域实体中定义我自己手工制作的属性(如
CrossPropertyErrors
)更多的值。WPF不支持以简单的内置方式测试
Error
属性

编辑:以上引用自2008年3月,因此很可能与.NET3.5有关。但我在.NET4.0中找不到任何迹象表明这一点发生了变化

编辑:最后,我必须创建自己的手写绑定到
错误
属性,并用适当的跨属性错误消息填充它。现在,类中任何其他属性的每次更改都会引发已更改属性本身和
Error
属性的
PropertyChanged
事件,以刷新UI上的错误消息

编辑2

大致如下:

模型(或视图模型)类:

公共类SomeModel:NotificationObject,IDataErrorInfo
{
私有字符串\u someProperty;
公共字符串属性
{
获取{return\u someProperty;}
设置
{
if(_someProperty!=值)
{
_someProperty=值;
RaisePropertyChanged(“SomeProperty”、“Error”);
//这是关键:对于每一个更改的属性,都有一个更改
//还会引发错误属性的通知
}
}
}
//对于模型的每个属性,上述操作都会重复
#区域IDataErrorInfo成员
公共字符串错误
{
得到
{
var sb=新的StringBuilder();
//例如。。。
如果(发票日期<发货日期)
sb.附录(“发票日期不得早于发货日期”);
//更多跨属性验证…我们只有一个错误
//字符串,因此我们用
//某人附加一句话(“另一条信息…”)等。
//可以全部移动到单独的验证类中
//保持模型类更干净
使某人返回字符串();
}
}
公共字符串此[string columnName]
{
得到
{
开关(列名称)
{
案例“发货日期”:
//属性级验证
案例“发票日期”:
//属性级验证
//等等。
}
返回null;
}
}
#端区
}
NotificationObject
实现
RaisePropertyChanged

公共抽象类NotificationObject:INotifyPropertyChanged
{
#区域INotifyPropertyChanged成员
公共事件属性更改事件处理程序属性更改;
#端区
受保护的虚拟void RaisePropertyChanged(字符串propertyName)
{
PropertyChangedEventHandler处理程序=PropertyChanged;
if(处理程序!=null)
处理程序(这是新的PropertyChangedEventArgs(propertyName));
}
受保护的void RaisePropertyChanged(参数字符串[]propertyNames)
{
if(propertyNames==null)
抛出新ArgumentNullException(“propertyNames”);
foreach(propertyNames中的变量名称)
RaisePropertyChanged(名称);
}