如何在ViewModel上使用数据注释?

发布于 2024-11-09 14:17:06 字数 1497 浏览 0 评论 0原文

我正在将 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; }
    }
}

我的问题是:如何确保 Name 在客户端被视为 Required 而不复制 ViewModel 中的所有注释? (将来我可能必须将这些实体与不同的 ViewModel 一起使用 - 并且我想保留相同的注释)

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

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

但是遗憾的是,MetadataTypeAttributeSystem.ComponentModel.DataAnnotations 的 Silverlight 5 版本中不可用。

编辑:澄清 - 我的实体的元数据包含在具有嵌套类的实体中。我手动编码此类,因为我的 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 服务代码生成器在客户端代码中生成正确的数据注释,因此它可以正确地获取它。

I'm using RIA Services with LinqToEntitiesDomainService<> and Silverlight 5 Beta to generate the DomainContext code on the client side. I have Data Annotations in my Models/Entities to do basic validations, and when using the Models directly, controls such as DataForm perform validations out-of-the-box. But I'm wrapping my Model in a ViewModel, so I lose all of that automatic validation. Here is a simplified example:

// 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; }
    }
}

My question is: how can I ensure that Name is considered Required on the client side without duplicating all of my annotations in the ViewModel? (I may have to use these Entities with different ViewModels in the future - and I'd like to keep the same annotations)

I thought of manually adding the MetadataType attribute to the ViewModel, pointing to the Model type:

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

But alas, MetadataTypeAttribute is not available in the Silverlight 5 version of System.ComponentModel.DataAnnotations.

Edit: Clarification - the metadata for my entities is included in the entities with a nested class. I code this class manually because my L2E model is in a separate assembly so the DomainService wizard would not generate it for me.

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

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

This should be exactly how the wizard would generate the metadata if I understand it correctly. The RIA Services code generator generates the right data annotations in the client code, so it's picking it up correctly.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我不在是我 2024-11-16 14:17:06

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

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

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

I found a way to do this. In hopes that it will help someone in the future:

I used a base class for the viewmodel that performs validations. On that base class I implement INotifyDataErrorInfo, and I override the NotifyOfPropertyChange method (This is part of Caliburn.Micro, but if you're not using you could just as easily attach to the PropertyChanged event for the model). In the event handler, I perform validation on that property. In the validation code, I use reflection to find the property of the same name, and any validation attributes on the property (RequiredAttribute, RangeAttribute, etc). Then I use the values from these properties to validate the new value on the changed property, creating ValidationResult objects and adding them to a List<ValidationResult>. If all of the 'local' validations pass, then I proceed to perform 'remote' validations (i.e. Validations that require interaction with the server, such as checking for uniqueness).

It was a lot of work, but unfortunately this - or something similar - is necessary. All of the MS examples appear to not use the MVVM. I thought this was just to keep them short/simple, but the Silverlight team at MS appears not to have given serious consideration MVVM when designing the object model.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文