none
EF, DataAnnotations, [Display(Name = "бла бла бла")] использование в приложениях RRS feed

  • Вопрос

  • Привет.

    Разбираюсь сейчас с EF. Встретил забавную штуку в DataAnnotations "Display(Name = "бла бла бла")".

    Собственно, если пометить ей поле\свойство, то затем можно вытянуть в программе написанный текст.

    Собственно, как это правильно сделать? Я погуглил, но в основном вся информация относится к ASP и локализации.

    Допустим, есть форма с датагридом (winforms), я в колонки хочу вывести названия полей класса, скажем в заголовок колонок в датагрид.

     public class TestEnum
        {
            [Key]
            public int TestEnumId { get; set; }
            public string Text { get; set; }
    
    
            [Display(Name = "Тип книжной обложки")]
            [EnumDataType(typeof(BookCoverType))]
            public BookCoverType CoverType { get; set; }
        }

    Я хочу, обратившись к полю, как нибудь автоматом вытянуть его название(в данном случае - Name). Это будет названием столбца в гриде. Или что-то еще.

    Как вытянуть руками\ через get only свойство класса я знаю - например для этого класса дополнительный код выглядит так:

     [NotMapped]
            public string CoverTypeLoc
            {
                get { return GetDisplayName(typeof(BookCoverType), CoverType); }
            }
    
    
            private static string GetDisplayName(Type dataType, object field)
            {
    
                if (field == null) return String.Empty;
    
    
                string fieldName = field.ToString();
    
                DisplayAttribute attr;
                FieldInfo fieldInfo;
                PropertyInfo propertyInfo;
    
                object[] b;
    
                if (dataType.BaseType == typeof(Enum))
                {
                    fieldInfo = dataType.GetField(fieldName);
                    b = fieldInfo.GetCustomAttributes(typeof(DisplayAttribute), true);
                }
                else
                {
                    propertyInfo = dataType.GetProperty(fieldName);
                    b = propertyInfo.GetCustomAttributes(typeof(DisplayAttribute), true);
                }
    
                if (b == null) return String.Empty;
    
    
                attr = (DisplayAttribute)b.SingleOrDefault();
    
                if (attr == null)
                {
                    var metadataType = (MetadataTypeAttribute)dataType.GetCustomAttributes(typeof(MetadataTypeAttribute), true).FirstOrDefault();
                    if (metadataType != null)
                    {
                        var property = metadataType.MetadataClassType.GetProperty(fieldName);
                        if (property != null)
                        {
                            attr = (DisplayAttribute)property.GetCustomAttributes(typeof(DisplayAttribute), true).SingleOrDefault();
                        }
                    }
                }
                return (attr != null) ? attr.Name : String.Empty;
            }

    Добавил get свойство, и метод, который вытягивает собственно текст (ну сейчас get вообще-то выдает название самого значения перечисления, но пока это не суть как важно).

    Добавив необходимое кол-во таких get свойств (по 1-2-3 на каждое, т.к. в реале могут использоватся не только Name, а и ShortName  и тд) я могу подвязывать их куда захочу.

    существуют ли иные механизмы получения данных, записанных таким образом? Что бы не создавать поля руками. Например:

    Label.Text = SomeClass.MyField.DisplayAttribute.Name;

    Может быть через расширения можно это сделать?

    Спасибо.

Ответы

  • Не уверен, что это будет работать на таблицах в WinForms, но это прекрасно работает в таблицах WPF. Там, если указать автогенерацию колонок, их имена берутся из этого поля. Так же там можно настроить ещё много различных вещей (валидацию, нужно ли это поле отображать и т.д.)
    • Помечено в качестве ответа Abolmasov Dmitry 25 мая 2012 г. 13:28
  • Для WinForms нужно использовать вместо Display, аттрибут DisplayName, например:
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            private void button1_Click(object sender, EventArgs e)
            {
                List<Test> d = new List<Test>();
                for (int i = 0; i < 10; i++)
                {
                    d.Add(new Test(i,i.ToString()));
                }
                dataGridView1.DataSource = d;
            }
        }
        public class Test
        {
            [DisplayName("номер")]
            public int Id { get; set; }
            [DisplayName("имя")]
            public String Name { get; set; }
            public Test(int id, string name)
            {
                Id = id;
                Name = name;
            }
        }


    Для связи [mail]

    • Помечено в качестве ответа Abolmasov Dmitry 25 мая 2012 г. 13:26

Все ответы

  • Display - это всего навсего стандартный атрибут, методанные. А читать значения атрибутов можно при помощи рефлексии, вот пример.
    Модератор
  • Добрый день, вот пример, иллюстрирующий практически вашу задачу.

    Отвечающий
  • Не уверен, что это будет работать на таблицах в WinForms, но это прекрасно работает в таблицах WPF. Там, если указать автогенерацию колонок, их имена берутся из этого поля. Так же там можно настроить ещё много различных вещей (валидацию, нужно ли это поле отображать и т.д.)
    • Помечено в качестве ответа Abolmasov Dmitry 25 мая 2012 г. 13:28
  • Для WinForms нужно использовать вместо Display, аттрибут DisplayName, например:
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            private void button1_Click(object sender, EventArgs e)
            {
                List<Test> d = new List<Test>();
                for (int i = 0; i < 10; i++)
                {
                    d.Add(new Test(i,i.ToString()));
                }
                dataGridView1.DataSource = d;
            }
        }
        public class Test
        {
            [DisplayName("номер")]
            public int Id { get; set; }
            [DisplayName("имя")]
            public String Name { get; set; }
            public Test(int id, string name)
            {
                Id = id;
                Name = name;
            }
        }


    Для связи [mail]

    • Помечено в качестве ответа Abolmasov Dmitry 25 мая 2012 г. 13:26
  • Dmitry Bondarenko DN, пожалуйста, не забудьте отметить ответ, который решает вашу проблему. Спасибо.

    Для связи [mail]