WPF 验证 ViewModel 中的自定义对象

WPF Validate custom objects in ViewModel

提问人:salttoinjury 提问时间:3/16/2023 最后编辑:Michal Divišsalttoinjury 更新时间:3/24/2023 访问量:196

问:

我正在使用 Mvvm Community Toolkit 的 ObservableValidator 来验证 viewmodel 属性。当我的视图模型中有一些自定义对象绑定到视图时,如何验证所有这些属性,而不必将所有模型属性移动到视图模型。

我真的不想用一堆验证属性来装饰我的领域模型,但我想用一些验证属性来装饰我的对象。

public class Product
{
    public int Id {get;set;}
    public string Name {get;set;}
}

public class MyViewModel : ObservableValidator
{
    private Product _product;
    
    [CustomValidation(typeof(MyViewModel), nameof(ValidateProduct))]      
    public Product Product 
    { 
      get => _product; 
      set => SetProperty(ref _product, value, false); 
    }
      
    public static ValidationResult ValidateProduct(string name, ValidationContext context)
    {
      //Do validation on all Product properties

      if(string.IsNullOrEmpty(Product.Name))
      {
        //Add validation result
      }  
    }
}

如何验证所有对象属性并将其添加到一些ValidationErrors列表中?它不必使用 Mvvm 社区工具包来完成。

C# WPF 验证 MVVM

评论


答:

0赞 Jürgen Röhr 3/24/2023 #1

当您查看 的实现时,您会发现仅当属性更改时才会触发验证。这意味着您必须设置整体才能触发验证。我假设,您绑定了输入字段(和其他属性),这不会发布属性的重新创建。ObservableValidator.SetPropertyProductProduct.NameProduct

我同意你不用 ui 相关的东西装饰域模型的意图。但 IMO 防止这种情况的正确方法是不要在 ui 中使用域模型。因此,如果是域模型,请将其从 中删除。相反,要么创建一个 full(它仍然可能是 的属性,但您需要设置一个本地属性以免弄乱绑定路径)或将所需的属性添加到您的 .然后,您可以在视图模型中执行输入验证。这还允许您使用标准验证规则,而不必实现自定义验证。ProductMyViewModelProductViewModelMyViewModelDataContextMyViewModel

由于域验证可能包括涉及相关域模型、当前状态等的复杂逻辑,这些逻辑在 UI 中不可用,因此我会进行基本验证(需要输入、范围内的日期/数字等),并在数据返回给域部分时进行全面验证。

评论

0赞 salttoinjury 3/24/2023
感谢您的反馈,我尝试基于域模型创建 DTO 并将我的验证属性放在那里,但没有成功。此外,我在执行命令时调用 ValidateAllProperties 方法(在 MvvM 工具包中可用),但它没有验证我的 DTO(这是 MyViewModel 上的属性)上的属性。我没有完全理解这部分“但您需要设置本地 DataContext 以免弄乱绑定路径”,View 的 DataContext 设置为 MyViewModel。
0赞 Jürgen Röhr 3/25/2023
@salttoinjury 关于“它不验证”:你为什么创建一个而不是一个.Dto 是否继承自 ?ProductDtoProductViewModelObservableValidator
0赞 Jürgen Röhr 3/25/2023
@salttoinjury 关于 DataContext:触发属性名称为 (引用 上的 “Name” 属性) 的事件。如果您已将属性设置为正确的路径,则该属性的正确路径将是...所以,这些不匹配。为了解决这个问题,你需要为你的产品输入创建一个容器,并将其设置为属性。SetPropertyPropertyChangedNameProductViewModelMyViewModelDataContextProduct.NameDataContextProduct