使用Catel将模型中的验证传播到View

时间:2014-12-01 10:14:40

标签: c# wpf mvvm catel

我正在使用Catel的MVVM(4.0.0)实现一个程序。我有一个模型类,作为一些业务逻辑 - 它必须遵守关于其中一个属性值的规则。

例如,假设我有一个Trap类,其中包含TargetValueCurrentValue属性。对于此类,有一条规则必须强制TargetValue属性只能小于或等于(< =)CurrentValue。 (CurrentValue通过系统中的某些事件更新。

陷阱向用户公开(我有一个VM,其中包含此类陷阱的列表并绑定到UI中的数据网格),她可以在其中更改TargetValue

最初我想创建一个VM来包装Trap对象实例并在那里强制执行规则,但由于规则实际上与模型(或业务逻辑)更相关,也就是说,我可能需要相同的规则在我使用Trap类的任何地方)我认为最好在TargetValue的属性设置器中实现它(我将检查新值的有效性并重置或不更改基础字段值)。

所以据说我在setter中做了(即使是正确的实现?) - 有没有办法通知VM(或UI直接)有违规行为(例如通过设置单元格边框颜色或其他东西) ?

我想也许我可以使用RaisePropertyChangingRaisePropertyChanged ObservableObject合作{{1}}虽然看起来很麻烦。

这种模式有适当的方法吗?

谢谢,

托默

2 个答案:

答案 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;常规"由于操作顺序,验证流程不会在这里发挥作用:

  • Property Setter
  • ValidateFields
  • 为VM
  • 准备好错误信息

解决方案应该如下:

  • CurrentValue属性设置器应该是私有的,因此无法直接绑定(通过使用装饰等直接或通过VM)
  • 添加到Trap课程IDataErrorInfo(或INotifyDataErrorInfo)实施
  • 实施一个SetCurrentValue函数,该函数验证数据并仅在合法时设置它。如果不是,请调用IDataErrorInfo机制。
  • 在UI中 - 绑定到函数而不是属性(例如http://msdn.microsoft.com/en-us/library/aa348824(v=vs.110).aspx

这种方法应该满足上述要求 - 在任何用例中属性值永远不会无效,但仍然可以与UI协调。