4

我使用 RIA 服务与 LinqToEntitiesDomainService<> 和 Silverlight 5 Beta 在客户端生成 DomainContext 代码。我的模型/实体中有数据注释来进行基本验证,当直接使用模型时,DataForm 等控件执行开箱即用的验证。但是我将我的模型包装在一个 ViewModel 中,所以我失去了所有的自动验证。这是一个简化的示例:

// In DataModel assembly, regenerated on the client side by RIA Services 
public class PetModel 
{
    [Required]
    public string Name { get; set; }
}

// Only on the client side
public class PetViewmodel
{
    private PetModel _model;

    public PetViewmodel(PetModel model)
    {
        _model = model;
    }

    public string Name
    {
        get { return _model.Name; }
        set { _model.Name = value; }
    }
}

我的问题是:如何确保在客户端不复制 ViewModel 中的所有注释的情况下Name考虑这一点?Required(将来我可能不得不将这些实体与不同的 ViewModel 一起使用——我想保留相同的注释)

我想到了手动将MetadataType属性添加到 ViewModel 中,指向 Model 类型:

[MetadataType(typeof(PetModel))]  
public class PetViewmodel
{
...
}

MetadataTypeAttribute很遗憾,在 Silverlight 5 版本的System.ComponentModel.DataAnnotations.

编辑:澄清 - 我的实体的元数据包含在具有嵌套类的实体中。我手动编码这个类,因为我的 L2E 模型在一个单独的程序集中,所以 DomainService 向导不会为我生成它。

[MetadataType(typeof(Metadata))]  
public partial class PetModel 
{
    [Required]
    public string Name { get; set; }

    public class Metadata 
    {
        [Required]
        public string Name { get; set; }
    }
}

如果我理解正确,这应该正是向导生成元数据的方式。RIA 服务代码生成器在客户端代码中生成正确的数据注释,因此它可以正确地提取它。

4

1 回答 1

1

我找到了一种方法来做到这一点。希望它对将来的某人有所帮助:

我为执行验证的视图模型使用了一个基类。在我实现的那个基类上INotifyDataErrorInfo,我重写了NotifyOfPropertyChange方法(这是Caliburn.Micro的一部分,但如果你不使用你可以很容易地附加到PropertyChanged模型的事件)。在事件处理程序中,我对该属性执行验证。在验证代码中,我使用反射来查找同名的属性,以及该属性上的任何验证属性(RequiredAttributeRangeAttribute等)。然后我使用这些属性中的值来验证已更改属性上的新值,创建ValidationResult对象并将它们添加到List<ValidationResult>. 如果所有“本地”验证都通过,那么我将继续执行“远程”验证(即需要与服务器交互的验证,例如检查唯一性)。

这是很多工作,但不幸的是,这 - 或类似的东西 - 是必要的。所有 MS 示例似乎都没有使用 MVVM。我认为这只是为了让它们简短/简单,但 MS 的 Silverlight 团队在设计对象模型时似乎没有认真考虑 MVVM。

于 2011-06-13T18:26:33.343 回答