[英]Propagate validation from Model to View with Catel
我正在使用Catel的MVVM(4.0.0)实现的程序。 我有一个模型类,作为一些业务逻辑-它必须遵守有关其属性值之一的规则。
例如,假设我有一个Trap
类,它具有TargetValue
和CurrentValue
属性。 对于此类,有一条规则必须强制TargetValue
属性只能小于或等于(<=) CurrentValue
。 ( CurrentValue
通过系统中的某些事件更新)。
陷阱向用户公开(我有一个VM,该VM拥有此类陷阱的列表,并绑定到UI中的数据网格),她可以在其中更改TargetValue
。
最初,我虽然创建了一个VM来包装Trap
对象实例并在那里执行规则,但是由于该规则实际上与模型更多相关(或业务逻辑,也就是说,在使用Trap
类的任何地方我都可能需要相同的规则)认为最好在TargetValue
的属性设置器中实现它(我将在其中检查新值的有效性,并重置或不更改基础字段值)。
因此,据说我是在setter中完成的(甚至是正确的实现吗?)-是否可以通过某种方式通知VM(或UI)是否存在违规情况(例如,通过设置单元格边框颜色或其他方式)?
我以为也许可以将ObservableObject
公开的RaisePropertyChanging
与RaisePropertyChanged
一起RaisePropertyChanged
,尽管看起来很麻烦。
是否有适当的方式来实现这种模式?
谢谢,
托默
您不应该在设置器中进行验证,因为设置器负责设置对象的值。 假设模型使用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将监视它的通知,并将视图模型上的属性映射到模型,反之亦然。 现在来了一件很酷的事情:它不仅映射属性值,还映射验证规则。 这意味着该视图模型足以满足您的视图需求,您可以在模型中实施验证。
在讨论了Catel的功能之后,由于操作的顺序,似乎通过“常规”验证流程无法解决问题:
解决方案应如下:
CurrentValue
属性设置器应该是私有的,这样就不能绑定到(直接或通过使用装饰等通过VM进行绑定) Trap
类IDataErrorInfo
(或INotifyDataErrorInfo
)实现 SetCurrentValue
函数,该函数验证数据并仅在合法的情况下进行设置。 否则,请调用IDataErrorInfo
机制。 这种方法应满足上述要求-属性值在任何使用情况下都不会无效,但仍可以与UI进行协调。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.