使用 Catel 将验证从模型传播到视图
本文关键字:传播 视图 模型 Catel 验证 使用 | 更新日期: 2023-09-27 18:32:48
我正在使用Catel的MVVM(4.0.0(实现开发一个程序。我有一个模型类,作为某些业务逻辑 - 它必须遵守有关其属性值之一的规则。
例如,假设我有一个具有TargetValue
和CurrentValue
属性的Trap
类。对于此类,有一个规则必须强制 TargetValue
属性只能小于或等于 (<=( CurrentValue
。(CurrentValue
通过系统中的某些事件更新(。
向用户公开(我有一个 VM,其中包含此类陷阱的列表并绑定到 UI 中的数据网格(,她可以在其中更改TargetValue
。
最初,我虽然创建一个 VM 来包装Trap
对象实例并在那里强制执行规则,但由于该规则实际上与模型(或业务逻辑,也就是说,我可能在我使用类Trap
任何地方都需要相同的规则(我认为最好在属性库中实现它TargetValue
(我将检查新值的有效性并重置或不更改基础字段值(。
所以据说我在 setter 中这样做(这甚至是一个正确的实现吗? - 有没有办法通知 VM(或直接 UI(存在违规(例如通过设置单元格边框颜色或其他方式(?
我想也许我可以与ObservableObject
公开的RaisePropertyChanged
合作使用RaisePropertyChanging
,尽管它看起来很麻烦。
这种模式有合适的方法吗?
谢谢
托默
您不应该在资源库中进行验证,因为资源库负责设置对象的值。假设模型使用 INotifyPropertyChanged 和 IDataErrorInfo(或 INotifyDataErrorInfo(,您可以使用 Catel 做大事。
例如,在模型库中,您可以覆盖 ValidateFields 或 ValidateBusinessRules,甚至可以将自定义验证程序应用于您的模型。然后,模型库将自动为您实现更改通知和验证接口。
接下来,虚拟机包含陷阱,例如下面的虚拟机(请注意,此示例使用 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 功能的讨论之后,由于操作顺序,通过"常规"验证流程似乎在这里不起作用:
- 属性设置器
- 验证字段
- 错误信息已准备好用于 VM
解决方案应该如下:
CurrentValue
属性资源库应该是私有的,以便它不能绑定到(直接或通过 VM 使用修饰等(- 添加到
Trap
类IDataErrorInfo
(或INotifyDataErrorInfo
(实现 - 实现一个
SetCurrentValue
函数,该函数验证数据并仅在合法时才设置数据。如果没有,请调用IDataErrorInfo
机制。 - 在 UI 中 - 绑定到函数而不是属性(例如 http://msdn.microsoft.com/en-us/library/aa348824(v=vs.110(.aspx(
此方法应满足上述要求 - 属性值在任何用例中都不会无效,但仍然可以与 UI 协调。