2012-02-21 10 views
5

Il DisplayAttribute in System.ComponentModel.DataAnnotation ha una proprietà GroupName, che consente di raggruppare logicamente i campi insieme in un controllo dell'interfaccia utente (ad esempio una griglia di proprietà in WPF/WinForms).Come recuperare l'annotazione dei dati GroupName da ModelMetadata

Sto tentando di accedere a questi metadati in un'applicazione ASP.NET MVC3, essenzialmente per creare una griglia di proprietà. Se il mio modello è simile al seguente:

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

e la mia vista si presenta così:

@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> 

allora la forma è disposto molto bene in base ai metadati, con le etichette, i suggerimenti, le filigrane ecc tutti tirato fuori dai metadati del modello; ma, vorrei poter raggruppare gli articoli insieme, ad esempio in un <fieldset> per gruppo. Qualcuno sa come estrarre il GroupName dai metadati, a meno di scrivere un metodo di estensione per ModelMetadata?

risposta

6

GroupName non analizzato dallo DataAnnotationsModelMetadataProvider. Quindi non c'è modo di farlo direttamente dall'oggetto ModelMetadata, anche con un metodo di estensione.

È possibile implementare il proprio provider che estende quello esistente per aggiungere il supporto per GroupName, che Brad Wilson explains in his blog.

È inoltre possibile scrivere il proprio attributo anziché utilizzare Display(GroupName =) e implementare l'interfaccia IMetadataAware per aggiungere il nome gruppo a ModelMetadata.AdditionalValues.

+0

Grazie, sembra proprio quello di cui ho bisogno. –

1

È inoltre possibile utilizzare questo metodo di estensione:

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

Poi

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

var groupName = display.Groupname; 
0

Un'alternativa potrebbe essere quella di utilizzare la proprietà ShortName della classe DisplayAttribute. Lo è esposto dalla classe ModelMetadata come proprietà ShortDisplayName.

Questo non è esattamente quello che stai cercando, ma ti permetterà di evitare di creare un'altra classe di attributi ... e per di più, puoi sfruttare l'abilità di localizzazione dello DisplayAttribute.

Problemi correlati