get the value of DisplayName attribute
Asked Answered
S

19

102
public class Class1
{
    [DisplayName("Something To Name")]
    public virtual string Name { get; set; }
}

How to get the value of DisplayName attribute in C# ?

Strasser answered 16/2, 2011 at 11:26 Comment(0)
L
108

Try these utility methods of mine:

using System.ComponentModel;
using System.Globalization;
using System.Linq;


public static T GetAttribute<T>(this MemberInfo member, bool isRequired)
    where T : Attribute
{
    var attribute = member.GetCustomAttributes(typeof(T), false).SingleOrDefault();

    if (attribute == null && isRequired)
    {
        throw new ArgumentException(
            string.Format(
                CultureInfo.InvariantCulture, 
                "The {0} attribute must be defined on member {1}", 
                typeof(T).Name, 
                member.Name));
    }

    return (T)attribute;
}

public static string GetPropertyDisplayName<T>(Expression<Func<T, object>> propertyExpression)
{
    var memberInfo = GetPropertyInformation(propertyExpression.Body);
    if (memberInfo == null)
    {
        throw new ArgumentException(
            "No property reference expression was found.",
            "propertyExpression");
    }

    var attr = memberInfo.GetAttribute<DisplayNameAttribute>(false);
    if (attr == null)
    {
        return memberInfo.Name;
    }

    return attr.DisplayName;
}

public static MemberInfo GetPropertyInformation(Expression propertyExpression)
{
    Debug.Assert(propertyExpression != null, "propertyExpression != null");
    MemberExpression memberExpr = propertyExpression as MemberExpression;
    if (memberExpr == null)
    {
        UnaryExpression unaryExpr = propertyExpression as UnaryExpression;
        if (unaryExpr != null && unaryExpr.NodeType == ExpressionType.Convert)
        {
            memberExpr = unaryExpr.Operand as MemberExpression;
        }
    }

    if (memberExpr != null && memberExpr.Member.MemberType == MemberTypes.Property)
    {
        return memberExpr.Member;
    }

    return null;
}

Usage would be:

string displayName = ReflectionExtensions.GetPropertyDisplayName<SomeClass>(i => i.SomeProperty);
Livesay answered 16/2, 2011 at 11:35 Comment(5)
Could u help me to find out proper way to iterate through all properties DisplayName, please? #12869401Riccardo
@rich-tebb It seems this doesn't work when you have [Display(Name = "SomeProperty", ResourceType = typeof(SomeResource))], it doesn't return localized name. Will try to modify it so it does.Centipoise
Added a little code snippet how to read the localized value from DisplayAttribute.Centipoise
public static T GetAttribute<T>(this extension method cannot be declared in a non-generic, non-nested static classSeeder
public static ThankYouAccumulative
T
45

First off, you need to get a MemberInfo object that represents that property. You will need to do some form of reflection:

MemberInfo property = typeof(Class1).GetProperty("Name");

(I'm using "old-style" reflection, but you can also use an expression tree if you have access to the type at compile-time)

Then you can fetch the attribute and obtain the value of the DisplayName property:

var attribute = property.GetCustomAttributes(typeof(DisplayNameAttribute), true)
      .Cast<DisplayNameAttribute>().Single();
string displayName = attribute.DisplayName;

() parentheses are required typo error

Temikatemp answered 16/2, 2011 at 11:32 Comment(1)
If the displayNameAttribute is null, this will fail. Instead of returning single try to return FirstOrDefault() then check whether this value is null or not.Teach
T
34

You need to get the PropertyInfo associated with the property (e.g. via typeof(Class1).GetProperty("Name")) and then call GetCustomAttributes.

It's a bit messy due to returning multiple values - you may well want to write a helper method to do this if you need it from a few places. (There may already be a helper method in the framework somewhere, but if there is I'm unaware of it.)

EDIT: As leppie pointed out, there is such a method: Attribute.GetCustomAttribute(MemberInfo, Type)

Tavi answered 16/2, 2011 at 11:30 Comment(2)
We got Attribute.GetCustomAttribute(MemberInfo, Type) :) msdn.microsoft.com/en-us/library/ms130863Untuck
@leppie: Ooh, nice. Not sure why I'd never spotted that.Tavi
C
14

If anyone is interested in getting the localized string from the property with DisplayAttribute and ResourceType like this:

[Display(Name = "Year", ResourceType = typeof(ArrivalsResource))]
public int Year { get; set; }

Use the following after displayAttribute != null (as shown above by @alex' answer):

ResourceManager resourceManager = new ResourceManager(displayAttribute.ResourceType);
var entry = resourceManager.GetResourceSet(Thread.CurrentThread.CurrentUICulture, true, true)
                           .OfType<DictionaryEntry>()
                           .FirstOrDefault(p => p.Key.ToString() == displayAttribute.Name);

return entry.Value.ToString();
Centipoise answered 4/12, 2013 at 18:45 Comment(6)
DisplayAttribute has GetName method. No need for your code in .NET 4+ : msdn.microsoft.com/en-us/library/…Apprise
@Apprise While you are correct you're slightly misled - when a ResourceType is specified, then the GetName() method just returns the Key, and not the Value specified in the resources file.Impede
@MattGriffiths what is this variable 'displayAttribute' ?Athematic
@Athematic that's probably the variable holding the result of that display attribute query, see https://mcmap.net/q/210101/-get-the-value-of-displayname-attribute for an example on how to do that.Beta
as pointed out by Salar, it's better to use .GetName() instead of the code above, see the problem I had with the code above here : #43827860Shielashield
Hi Matija , I'm looking for some help here in my question, I think maybe you could have some knowledge related. Thanks! #5016330Questionless
C
13
var propInfo = typeof(Class1).GetProperty("Name");
var displayNameAttribute = propInfo.GetCustomAttributes(typeof(DisplayNameAttribute), false);
var displayName = (displayNameAttribute[0] as DisplayNameAttribute).DisplayName;

displayName variable now holds the property's value.

Crownpiece answered 2/1, 2018 at 16:28 Comment(2)
That looks so hackyTropicalize
I already had the propertyinfo and this is just what I needed. :-) And I did the missing null check with firstanddefault and "is".Gracie
P
12

From within a view that has Class1 as it's strongly typed view model:

ModelMetadata.FromLambdaExpression<Class1, string>(x => x.Name, ViewData).DisplayName;
Plucky answered 16/2, 2011 at 11:31 Comment(2)
I think this should be the accepted answer... I assume it's smart enough to use the cached metadata objects internally; either way, nice and concise and using .net's own methodsAntoninaantonino
Only available via System.Web.Mvc - not everybody does web apps, even in 2020..Beta
A
10

Nice classes by Rich Tebb! I've been using DisplayAttribute and the code did not work for me. The only thing I've added is handling of DisplayAttribute. Brief search yielded that this attribute is new to MVC3 & .Net 4 and does almost the same thing plus more. Here's a modified version of the method:

 public static string GetPropertyDisplayString<T>(Expression<Func<T, object>> propertyExpression)
    {
        var memberInfo = GetPropertyInformation(propertyExpression.Body);
        if (memberInfo == null)
        {
            throw new ArgumentException(
                "No property reference expression was found.",
                "propertyExpression");
        }

        var displayAttribute = memberInfo.GetAttribute<DisplayAttribute>(false);

        if (displayAttribute != null)
        {
            return displayAttribute.Name;
        }
        else
        {
            var displayNameAttribute = memberInfo.GetAttribute<DisplayNameAttribute>(false);
            if (displayNameAttribute != null)
            {
                return displayNameAttribute.DisplayName;
            }
            else
            {
                return memberInfo.Name;
            }
        }
    }
Adel answered 6/4, 2012 at 20:15 Comment(0)
L
4

I have this generic utility method. I pass in a list of a given type (Assuming you have a supporting class) and it generates a datatable with the properties as column headers and the list items as data.

Just like in standard MVC, if you dont have DisplayName attribute defined, it will fall back to the property name so you only have to include DisplayName where it is different to the property name.

    public DataTable BuildDataTable<T>(IList<T> data)
    {
        //Get properties
        PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
        //.Where(p => !p.GetGetMethod().IsVirtual && !p.GetGetMethod().IsFinal).ToArray(); //Hides virtual properties

        //Get column headers
        bool isDisplayNameAttributeDefined = false;
        string[] headers = new string[Props.Length];
        int colCount = 0;
        foreach (PropertyInfo prop in Props)
        {
            isDisplayNameAttributeDefined = Attribute.IsDefined(prop, typeof(DisplayNameAttribute));

            if (isDisplayNameAttributeDefined)
            {
                DisplayNameAttribute dna = (DisplayNameAttribute)Attribute.GetCustomAttribute(prop, typeof(DisplayNameAttribute));
                if (dna != null)
                    headers[colCount] = dna.DisplayName;
            }
            else
                headers[colCount] = prop.Name;

            colCount++;
            isDisplayNameAttributeDefined = false;
        }

        DataTable dataTable = new DataTable(typeof(T).Name);

        //Add column headers to datatable
        foreach (var header in headers)
            dataTable.Columns.Add(header);

        dataTable.Rows.Add(headers);

        //Add datalist to datatable
        foreach (T item in data)
        {
            object[] values = new object[Props.Length];
            for (int col = 0; col < Props.Length; col++)
                values[col] = Props[col].GetValue(item, null);

            dataTable.Rows.Add(values);
        }

        return dataTable;
    }

If there's a more efficient / safer way of doing this, I'd appreicate any feedback. The commented //Where clause will filter out virtual properties. Useful if you are using model classes directly as EF puts in "Navigation" properties as virtual. However it will also filter out any of your own virtual properties if you choose to extend such classes. For this reason, I prefer to make a ViewModel and decorate it with only the needed properties and display name attributes as required, then make a list of them.

Hope this helps.

Lebaron answered 3/12, 2014 at 15:17 Comment(0)
A
3
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(foo);

foreach (PropertyDescriptor property in properties)
{
    if (property.Name == "Name")
    {
        Console.WriteLine(property.DisplayName); // Something To Name
    }
}

where foo is an instance of Class1

Alain answered 1/6, 2014 at 20:5 Comment(0)
F
2

Assuming property as PropertyInfo type, you can do this in one single line:

property.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().Single().DisplayName
Faris answered 21/1, 2015 at 22:18 Comment(0)
M
2

Late to the party I know.

I use this:

public static string GetPropertyDisplayName(PropertyInfo pi)
{
  var dp = pi.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().SingleOrDefault();
  return dp != null ? dp.DisplayName : pi.Name;
}

Hope this helps.

Medallist answered 11/4, 2020 at 5:55 Comment(0)
L
1

Try this code:

EnumEntity.item.GetType().GetFields()[(int)EnumEntity.item].CustomAttributes.ToArray()[0].NamedArguments[0].TypedValue.ToString()

It will give you the value of data attribute Name.

Limacine answered 8/3, 2017 at 18:16 Comment(0)
S
1

This works, thanks to someone above:

foreach (PropertyInfo pi in properties)
{
    var propName = pi.Name;
    var dp = pi.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().SingleOrDefault();
    if (dp != null)
    {
        propName = dp.DisplayName; 
    }
}
Silvestro answered 25/6, 2021 at 16:39 Comment(0)
S
1

if you're here for [Display(Name="")] below code might help:

var props = yourObject.GetType().GetProperties();
foreach (var item in props)
{
   string title = item.GetCustomAttributes(typeof(DisplayAttribute), true).Cast<DisplayAttribute>().SingleOrDefault()?.Name;
}
Stenson answered 24/11, 2021 at 11:8 Comment(0)
E
1
PropertyInfo[] properties = typeof(T).GetProperties();
String displayName = null;
foreach (PropertyInfo pi in properties){
     var displayAttribute = pi.GetCustomAttribute(typeof(DisplayAttribute));
    if (displayAttribute != null)
                {
                    displayName = (displayAttribute as DisplayAttribute).GetName();
                }
            }
Electrochemistry answered 22/12, 2021 at 11:32 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Dabster
C
0

Following Rich Tebb's and Matt Baker's answer, I wanted to use the ReflectionExtensions methods in a LINQ query, but it didn't work, so I've made this method for it to work.

If DisplayNameAttribute is set the method will return it, otherwise it will return the MemberInfo name.

Test method:

static void Main(string[] args)
{
    var lst = new List<Test>();
    lst.Add(new Test("coucou1", "kiki1"));
    lst.Add(new Test("coucou2", "kiki2"));
    lst.Add(new Test("coucou3", "kiki3"));
    lst.Add(new Test("coucou4", "kiki4"));
    lst.ForEach(i => 
        Console.WriteLine(i.GetAttributeName<Test>(t => t.Name) + ";" + i.GetAttributeName<Test>(t=>t.t2)));
}

Test method output:

Test method output

The class with DisplayName1 Attribute:

public class Test
{
    public Test() { }
    public Test(string name, string T2)
    {
        Name = name;
        t2 = T2;
    }
    [DisplayName("toto")]
    public string Name { get; set; }
    public string t2 { get; set; }
}

And the extension method:

public static string GetAttributeName<T>(this T itm, Expression<Func<T, object>> propertyExpression)
{
    var memberInfo = GetPropertyInformation(propertyExpression.Body);
    if (memberInfo == null)
    {
        throw new ArgumentException(
            "No property reference expression was found.",
            "propertyExpression");
    }

    var pi = typeof(T).GetProperty(memberInfo.Name);
    var ret = pi.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().SingleOrDefault();
    return ret != null ? ret.DisplayName : pi.Name;

}

Coxswain answered 27/2, 2017 at 13:21 Comment(1)
GetPropertyInformation() does not exist in this context. I've just realised that this code is present in an answer belowGiacopo
S
0

Please try below code, I think this will solve your problem.

var classObj = new Class1();
classObj.Name => "StackOverflow";

var property = new Class1().GetType().GetProperty(nameof(classObj.Name));
var displayNameAttributeValue = (property ?? throw new InvalidOperationException())
    .GetCustomAttributes(typeof(DisplayNameAttribute)) as DisplayNameAttribute; 

if (displayNameAttributeValue != null)
{
   Console.WriteLine("{0} = {1}", displayNameAttributeValue, classObj.Name);
}
Saltine answered 1/11, 2018 at 12:54 Comment(1)
Please add some explanation / inline code comments to explain how your code works and will solve OP's query.Willtrude
S
0

If instead

[DisplayName("Something To Name")]

you use

[Display(Name = "Something To Name")]

Just do this:

private string GetDisplayName(Class1 class1)
{
    string displayName = string.Empty;

    string propertyName = class1.Name.GetType().Name;

    CustomAttributeData displayAttribute = class1.GetType().GetProperty(propertyName).CustomAttributes.FirstOrDefault(x => x.AttributeType.Name == "DisplayAttribute");

    if (displayAttribute != null)
    {
        displayName = displayAttribute.NamedArguments.FirstOrDefault().TypedValue.Value;
    }

    return displayName;
}
Soria answered 27/4, 2020 at 18:16 Comment(0)
C
-1

This code worked for me...

Class definition:

using System.ComponentModel.DataAnnotations;

public class Class1{
     [Display(Name = "Something To Name")]
     public string PropertyOfMyClass1{ get; set; } 
 }

in your own method:

using System.Web.Mvc;

string displayName = ModelMetadata.FromLambdaExpression(x => x.PropertyOfMyClass1, new ViewDataDictionary<Class1>()).DisplayName;

Result:

displayName --> "Something To Name"

in your code change PropertyOfMyClass1 and Class1 with your own values.

Cribbing answered 22/10, 2023 at 9:30 Comment(1)
Your answer doesn't provide more information than the existing answers (especially this one), I think you should read the help center for answers, especially How to answer? and Reasons leading to answer deletionFarra

© 2022 - 2024 — McMap. All rights reserved.