WPF MVVM:ObservableValidator结合后台Model的最优实现方案咨询
MVVM-Toolkit中ViewModel绑定Model属性的验证问题
我现在的代码结构如下:
public class MyModel { public string MyProperty { get; set; } } public class MyViewModel: ObservableValidator { private MyModel mModelInstance; public MyViewModel(MyModel modelInstance){ this.mModelInstance = modelInstance; } [MinLength(20)] public string MyProperty { get => mModelInstance.MyProperty; set => SetProperty(ref mModelInstance.MyProperty, value, validate = true); // 此处报错:mModelInstance.MyProperty是属性,不能按ref传递 } }
我想到了三种可行的解决办法,但不确定哪种最优:
方案1:把验证逻辑和
PropertyChanged移到Model层。给MyModel的MyProperty添加私有后台字段,然后在ViewModel里暴露ModelInstance属性。这样就能在MyModel.MyProperty的setter里调用SetProperty(ref mMyProperty, value, validate = true)。方案2:把
MyModel.MyProperty改成公共字段而非属性。但我知道这是不良实践,就算是POCO类这么做也不合适吧?方案3:不依赖
SetProperty的单一调用,在ViewModel的MyPropertysetter里分开执行三步:set { mModelInstance.MyProperty = value; OnPropertyChanged(); ValidateProperty(value); }这个方案不用修改Model(依然保留公共属性),是我原本倾向的选择,但因为要写三个独立语句,而不是用MVVM-Toolkit提供的封装调用,我有点拿不定主意。
方案分析与推荐
方案1的优劣:
- 优点:把状态变更和验证逻辑内聚到Model,符合领域模型的设计原则,ViewModel只做数据转发,职责更单一。
- 缺点:如果Model原本是纯POCO(比如用于ORM映射),修改后会引入MVVM-Toolkit的依赖,破坏POCO的纯净性;而且如果多个ViewModel依赖同一个Model,Model的验证逻辑可能无法适配所有场景。
方案2的优劣:
- 优点:改动最小,能直接用
SetProperty。 - 缺点:公共字段违背了封装原则,无法在字段变更时添加额外逻辑(比如校验、日志),后续维护扩展性极差,绝对不推荐。
- 优点:改动最小,能直接用
方案3的优劣:
- 优点:完全保留Model的POCO特性,不需要修改Model结构;ViewModel依然能掌控验证逻辑,灵活性高,不同ViewModel可以给同一个Model属性加不同的验证规则。
- 缺点:相比
SetProperty多写了两行代码,但这三行逻辑清晰,并没有增加维护成本——SetProperty本质上也是封装了这几个步骤,只是这里手动展开而已。
最优选择:优先选方案3。它既不破坏Model的设计,又能满足ViewModel的验证和通知需求,代码逻辑直观,后续也方便调整验证规则。如果你的Model本身就需要承载业务逻辑和验证,那方案1也是合理的,但如果Model是纯数据载体,方案3是更合适的折中。
内容的提问来源于stack exchange,提问作者Marc Miller
相关产品推荐
相关产品推荐

