我正在使用Catel的MVVM(4.0.0)实现一个程序。我有一个模型类,作为一些业务逻辑 - 它必须遵守关于其中一个属性值的规则。
例如,假设我有一个Trap
类,其中包含TargetValue
和CurrentValue
属性。对于此类,有一条规则必须强制TargetValue
属性只能小于或等于(< =)CurrentValue
。 (CurrentValue
通过系统中的某些事件更新。
陷阱向用户公开(我有一个VM,其中包含此类陷阱的列表并绑定到UI中的数据网格),她可以在其中更改TargetValue
。
最初我想创建一个VM来包装Trap
对象实例并在那里强制执行规则,但由于规则实际上与模型(或业务逻辑)更相关,也就是说,我可能需要相同的规则在我使用Trap
类的任何地方)我认为最好在TargetValue
的属性设置器中实现它(我将检查新值的有效性并重置或不更改基础字段值)。
所以据说我在setter中做了(即使是正确的实现?) - 有没有办法通知VM(或UI直接)有违规行为(例如通过设置单元格边框颜色或其他东西) ?
我想也许我可以使用RaisePropertyChanging
与RaisePropertyChanged
ObservableObject
合作{{1}}虽然看起来很麻烦。
这种模式有适当的方法吗?
谢谢,
托默
答案 0 :(得分:1)
您不应该在setter中进行验证,因为setter负责设置对象的值。假设模型使用INotifyPropertyChanged和IDataErrorInfo(或INotifyDataErrorInfo),您可以使用Catel做大事。
例如,在ModelBase中,您可以覆盖ValidateFields或ValidateBusinessRules,甚至可以将自定义验证器应用于模型。然后,ModelBase将自动为您实现更改通知和验证接口。
接下来,VM包含陷阱,例如下面的vm(请注意,此示例使用Catel.Fody):
public class MyTrapViewModel : ViewModelBase
{
public MyTrapViewModel(Trap trap)
{
Argument.IsNotNull(() => trap);
Trap = trap;
}
[Model]
[Expose("CurrentValue")]
[Expose("TargetValue")]
private Trap Trap { get; set; }
}
在此示例中,您将Trap
属性定义为模型。这意味着Catel将观察它以获取通知并将视图模型上的属性映射到模型,反之亦然。现在来了很酷的事情:它不仅仅映射属性值,它也映射了验证规则。这意味着此视图模型对于您的视图就足够了,您可以在模型中实现验证。
答案 1 :(得分:1)
在讨论了Catel的功能后,似乎经历了#34;常规"由于操作顺序,验证流程不会在这里发挥作用:
解决方案应该如下:
CurrentValue
属性设置器应该是私有的,因此无法直接绑定(通过使用装饰等直接或通过VM)Trap
课程IDataErrorInfo
(或INotifyDataErrorInfo
)实施SetCurrentValue
函数,该函数验证数据并仅在合法时设置它。如果不是,请调用IDataErrorInfo
机制。这种方法应该满足上述要求 - 在任何用例中属性值永远不会无效,但仍然可以与UI协调。