The DisplayAttribute in System.ComponentModel.DataAnnotations has a GroupName property, which allows you to logically group fields together in a UI control (e.g. a property grid in WPF/WinForms).
I am trying to access this metadata in an ASP.NET MVC3 application, essentially to create a property grid. If my model looks like this:
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; }
}
and my view looks like this:
@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>
then the form is laid out very nicely based on the metadata, with labels, tooltips, watermarks etc all pulled out of the model's metadata; but, I would like to be able to group the items together, for instance in a <fieldset>
per group. Does anyone know how to get the GroupName out of the metadata, short of writing an extension method for ModelMetadata?
GroupName
is not parsed by the DataAnnotationsModelMetadataProvider
. So there's no way to get it right off the ModelMetadata
object, even with an extension method.
You could implement your own provider that extends the existing one to add support for GroupName, which Brad Wilson explains in his blog.
You could also write your own attribute instead of using Display(GroupName = )
and implement the IMetadataAware
interface to add the groupname to ModelMetadata.AdditionalValues
.
You can also use this Extension Method:
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;
}
}
Then
var display= this.ViewData.ModelMetadata
.GetPropertyAttribute<DisplayAttribute>();
var groupName = display.Groupname;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With