C# 使用Catel将验证从模型传播到视图
我正在开发一个使用Catel的MVVM(4.0.0)实现的程序。我有一个模型类,作为一些业务逻辑,它必须遵守关于它的属性值之一的规则C# 使用Catel将验证从模型传播到视图,c#,wpf,mvvm,catel,C#,Wpf,Mvvm,Catel,我正在开发一个使用Catel的MVVM(4.0.0)实现的程序。我有一个模型类,作为一些业务逻辑,它必须遵守关于它的属性值之一的规则 例如,假设我有一个Trap类,它有一个TargetValue和一个CurrentValue属性。对于此类,有一条规则必须强制执行TargetValue属性只能小于或等于(您不应该在setter中验证,因为setter负责设置对象的值。假设模型使用INotifyPropertyChanged和IDataErrorInfo(或INotifyDataErrorInfo)
例如,假设我有一个
Trap
类,它有一个TargetValue
和一个CurrentValue
属性。对于此类,有一条规则必须强制执行TargetValue
属性只能小于或等于(您不应该在setter中验证,因为setter负责设置对象的值。假设模型使用INotifyPropertyChanged和IDataErrorInfo(或INotifyDataErrorInfo),你可以用卡特尔做大事
例如,在ModelBase中,您可以覆盖ValidateFields或ValidateBusiness规则,甚至可以对您的模型应用自定义验证器。然后ModelBase将自动为您实现更改通知和验证接口
接下来,VM包含陷阱,例如下面的VM(请注意,此示例使用Catel.Fody):
在本例中,您将
Trap
属性定义为model。这意味着Catel将监视它以获取通知,并将视图模型上的属性映射到模型,反之亦然。现在有一件很酷的事情:它不仅映射属性值,还映射验证规则。这意味着该视图模型就足够了您不应该在setter中进行验证,因为setter负责设置对象的值。假设模型使用INotifyPropertyChanged和IDataErrorInfo(或INotifyDataErrorInfo),您可以使用Catel做大事
例如,在ModelBase中,您可以覆盖ValidateFields或ValidateBusiness规则,甚至可以对您的模型应用自定义验证器。然后ModelBase将自动为您实现更改通知和验证接口
接下来,VM包含陷阱,例如下面的VM(请注意,此示例使用Catel.Fody):
在本例中,您将
Trap
属性定义为model。这意味着Catel将监视它以获取通知,并将视图模型上的属性映射到模型,反之亦然。现在有一件很酷的事情:它不仅映射属性值,还映射验证规则。这意味着该视图模型就足够了您可以在模型中实施验证。在讨论了Catel的功能后,由于操作顺序的原因,似乎通过“常规”验证流程无法实现此目的:
- 属性设置器
- 验证字段
- 错误信息已准备好用于虚拟机
属性设置器应该是私有的,这样它就不能被绑定到(直接绑定或使用装饰等通过VM绑定)CurrentValue
- 添加到
类Trap
(或IDataErrorInfo
)实现中INotifyDataErrorInfo
- 实现一个
函数,该函数验证数据并仅在合法的情况下进行设置。如果不合法,则调用SetCurrentValue
机制IDataErrorInfo
- 在UI中-绑定到函数而不是属性(例如)
此方法应满足上述要求-属性值在任何用例中都不会无效,但仍然可以与UI协调。在讨论了Catel的功能后,由于操作顺序的原因,通过“常规”验证流程似乎无法达到目的:
- 属性设置器
- 验证字段
- 错误信息已准备好用于虚拟机
属性设置器应该是私有的,这样它就不能被绑定到(直接绑定或使用装饰等通过VM绑定)CurrentValue
- 添加到
类Trap
(或IDataErrorInfo
)实现中INotifyDataErrorInfo
- 实现一个
函数,该函数验证数据并仅在合法的情况下进行设置。如果不合法,则调用SetCurrentValue
机制IDataErrorInfo
- 在UI中-绑定到函数而不是属性(例如)
此方法应满足上述要求-属性值在任何用例中都不会无效,但仍然可以与UI协调。我使用
observeObject
作为模型类的基础,以保持简单。据我所见,此类不支持require机制。我可能会更改它(虽然由于“开销”我不太愿意,但我认为(如果我错了,请纠正我)验证可能会标记错误,但基础值仍将更改-或者它是否完全“取消”更新?如果它不取消,此解决方案将不适用于我,因为其他线程我的“监视”此(陷阱)对象,并可能使用非法值。您仍然可以使用ObserveObject,但如果需要验证,您a)需要自己编写,或者b)使用经过多年优化的Catel。这取决于您。我毫不怀疑Catel的代码比我编写的任何代码都好。我关心的是事件的实际顺序-使用内部验证是否可以解决我的问题-如果存在验证错误-它是否会阻止实际更新属性?假设我使用ValidateFields-我在函数中检查条件的属性值,我可以发出错误/警告-但由于违反了条件,时间已经太晚了…或者我缺少了什么?您只能验证(并保持验证状态)如果该属性确实可以设置。那么您可以设置该属性,但是模型将无效(这是正常行为)。谢谢
public class MyTrapViewModel : ViewModelBase
{
public MyTrapViewModel(Trap trap)
{
Argument.IsNotNull(() => trap);
Trap = trap;
}
[Model]
[Expose("CurrentValue")]
[Expose("TargetValue")]
private Trap Trap { get; set; }
}