2012-02-21 15 views
5

DisplayAttribute en System.ComponentModel.DataAnnotations tiene una propiedad GroupName, que le permite agrupar lógicamente campos juntos en un control de IU (por ejemplo, una cuadrícula de propiedades en WPF/WinForms).Cómo recuperar la anotación de datos de GroupName de ModelMetadata

Estoy intentando tener acceso a estos metadatos en una aplicación ASP.NET MVC3, esencialmente para crear una cuadrícula de propiedades. Si mi modelo es el siguiente:

public class Customer 
{ 
    [ReadOnly] 
    public int Id { get;set; } 

    [Display(Name = "Name", Description = "Customer's name", GroupName = "Basic")] 
    [Required(ErrorMessage = "Please enter the customer's name")] 
    [StringLength(255)] 
    public string Name { get;set; } 

    [Display(Name = "Email", Description = "Customer's primary email address", GroupName = "Basic")] 
    [Required] 
    [StringLength(255)] 
    [DataType(DataType.Email)] 
    public string EmailAddress { get;set; } 

    [Display(Name = "Last Order", Description = "The date when the customer last placed an order", GroupName = "Status")] 
    public DateTime LastOrderPlaced { get;set; } 

    [Display(Name = "Locked", Description = "Whether the customer account is locked", GroupName = "Status")] 
    public bool IsLocked { get;set; } 
} 

y mi vista se ve así:

@model Customer 

<div class="edit-customer"> 
    @foreach (var property in ViewData.ModelMetadata.Properties.Where(p => !p.IsReadOnly).OrderBy(p => p.Order)) 
    { 
     <div class="editor-row"> 
      @Html.DevExpress().Label(settings => 
       { 
        settings.AssociatedControlName = property.PropertyName; 
        settings.Text = property.DisplayName; 
        settings.ToolTip = property.Description; 
       }).GetHtml() 
      <span class="editor-field"> 
       @Html.DevExpress().TextBox(settings => 
        { 
         settings.Name = property.PropertyName; 
         settings.Properties.NullText = property.Watermark; 
         settings.Width = 200; 
         settings.Properties.ValidationSettings.RequiredField.IsRequired = property.IsRequired; 
         settings.ShowModelErrors = true; 
        }).Bind(ViewData[property.PropertyName]).GetHtml() 
      </span> 
     </div> 
    } 
</div> 

entonces la forma se presenta muy bien sobre la base de los metadatos, con etiquetas, información sobre herramientas, marcas de agua, etc., todo tirado fuera de los metadatos del modelo; pero, me gustaría ser capaz de agrupar los elementos juntos, por ejemplo en un <fieldset> por grupo. ¿Alguien sabe cómo sacar el nombre de grupo de los metadatos, sin escribir un método de extensión para ModelMetadata?

Respuesta

6

GroupName no es analizada por el DataAnnotationsModelMetadataProvider. Por lo tanto, no hay forma de eliminarlo directamente del objeto ModelMetadata, incluso con un método de extensión.

podría implementar su propio proveedor que se extiende la ya existente para añadir soporte para NombreGrupo, que Brad Wilson explains in his blog.

También podría escribir su propio atributo en lugar de usar Display(GroupName =) e implementar la interfaz IMetadataAware para agregar el nombre de grupo a ModelMetadata.AdditionalValues.

+0

Gracias, que se parece justo lo que necesito. –

1

También puede utilizar este método de extensión:

public static class ModelMetadataExtensions 
{ 
    public static T GetPropertyAttribute<T>(this ModelMetadata instance) 
    where T : Attribute 
    { 
    var result = instance.ContainerType 
     .GetProperty(instance.PropertyName) 
     .GetCustomAttributes(typeof(T), false) 
     .Select(a => a as T) 
     .FirstOrDefault(a => a != null); 

    return result; 
    } 
} 

Entonces

var display= this.ViewData.ModelMetadata 
    .GetPropertyAttribute<DisplayAttribute>(); 

var groupName = display.Groupname; 
0

Una alternativa podría ser el uso de la propiedad de la clase ShortNameDisplayAttribute. Es es expuesto por la clase ModelMetadata como la propiedad ShortDisplayName.

Esto no es exactamente lo que está buscando, pero le permitirá evitar crear otra clase de atributo ... y además de eso, puede aprovechar la capacidad de localización del DisplayAttribute.

Cuestiones relacionadas