What's DisplayAttribute.GroupName property used for?

我们两清 提交于 2019-12-22 11:09:04

问题


I'm trying to figure out the valid usages of DisplayAttribute.GroupName property.

MSDN says:

A value that is used to group fields in the UI.

but I wouldn't call it a comprehensive explanation. It makes me think that GroupName can be used to create groupboxes around certain fields. But then the remark:

Do not use this property to get the value of the GroupName property. Use the GetDescription method instead. A null value or empty string is valid.

seems to contradict it.

So what is this property for and should I use it (probably with custom template or custom ModelMetadataProvider) in order to render groupboxes around my fields?


回答1:


In the MVC RTM source code there is no sign of usage.

The "GetDescription" remark might be a copy/paste error in the documentation (each string property seems to have a GetXXX counterpart that returns a localizable value), so it should be most probably "GetGroupName" in this case.

UPDATE: I would use it exactly for that: group fields together that belong together from the UI point-of-view. As this is just data annotation on the model, it declares only that these fields belong to one logical group "somehow" on the UI, the but concrete presentation details depend on the "UI engine" that displays the model based on the metadata. I think the most meaningful way to "render" this on the UI is exactly what you said: wrapping the grouped fields into a section or fieldset.

Of course there might be future extensions of MVC or other custom extensions that do some kind of grouping on the UI "automatically" (without writing custom code that examines the metadata and generates the sections) based on this attribute property. But I'm quite sure that such an extension would do something very similar that you would do currently.




回答2:


I ended up writing this class to make the GroupName more easily accessible:

public class ExtendedDataAnnotationsModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
    public const string Key_GroupName = "GroupName";

    protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
    {
        ModelMetadata modelMetadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
        DisplayAttribute displayAttribute = attributes.OfType<DisplayAttribute>().FirstOrDefault();

        if (displayAttribute != null)
            modelMetadata.AdditionalValues[ExtendedDataAnnotationsModelMetadataProvider.Key_GroupName] = displayAttribute.GroupName;

        return modelMetadata;
    }
}

And this extension method:

public static string GetGroupName(this ModelMetadata modelMetadata)
{
    if (modelMetadata.AdditionalValues.ContainsKey(ExtendedDataAnnotationsModelMetadataProvider.Key_GroupName))
        return (modelMetadata.AdditionalValues[ExtendedDataAnnotationsModelMetadataProvider.Key_GroupName] as string);

    return null;
}

Source: http://bradwilson.typepad.com/blog/2010/01/why-you-dont-need-modelmetadataattributes.html




回答3:


How About This !!! Must Work :

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Web;
using System.Web.Mvc;

namespace System.Web.Mvc
{
    public static class DisplayGroup
    {
        public static MvcHtmlString DisplayGroupName(this HtmlHelper helper, string groupName)
        {
            return MvcHtmlString.Create(groupName);
        }

        public static MvcHtmlString DisplayGroupNameFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
        {
            var type = typeof(TModel);
            PropertyInfo propertyInfo = null;

            var member = (MemberExpression)expression.Body;
            var property = (PropertyInfo)member.Member;
            var name = property.Name;

            var metadataTypeInfo = type.GetCustomAttribute<MetadataTypeAttribute>();

            if (metadataTypeInfo != null)
            {
                var metadataType = metadataTypeInfo.MetadataClassType;
                propertyInfo = metadataType.GetProperties().Where(x => x.Name == name).FirstOrDefault();
                if (propertyInfo == null)
                {
                    propertyInfo = type.GetProperties().Where(x => x.Name == name).FirstOrDefault();
                }
            }
            else
            {
                propertyInfo = type.GetProperties().Where(x => x.Name == name).FirstOrDefault();
            }

            string output = "";

            var dattr = propertyInfo.GetCustomAttribute<DisplayAttribute>();
            if (dattr != null)
            {
                if (dattr.GroupName == null)
                {
                    output = propertyInfo.Name;
                }
                else
                {
                    output = dattr.GroupName;
                }
            }
            else
            {
                output = propertyInfo.Name;
            }

            return MvcHtmlString.Create(output);
        }

    }
}




public class MyModel
    {
        [Display(Name = "Number",GroupName="Invoice")]
        string InvNo { get; set; }
    }

and then simply write :

@Html.DisplayGroupNameFor(x => x.InvNo)

Note : NameSpace should be : System.Web.Mvc

Update : The cool thing is that , if you have a MetaDataType class defined for your dataAnnotation , then also this will work as expected.



来源:https://stackoverflow.com/questions/6649505/whats-displayattribute-groupname-property-used-for

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!