2012-02-15 3 views
3

У меня есть viewmodel, где свойства имеют отображаемые имена. Теперь я делаю лист Excel с теми же данными, что и сетка на веб-странице. Я использую closed xml (с использованием openxml), чтобы создать Excelsheet на сервере и отправить его веб-клиенту, когда они хотят загрузить данные в формате Excel. Когда я пишу строку заголовка в потоке Excel openxml, я хочу повторно использовать отображаемое имя, которое я уже определил. Но я не могу понять, что нужно. Ниже приведен пример отображаемого имени. (Для примера я использую только два, реальность есть много много больше столбцов):Как получить доступ к System.ComponentModel.DataAnnotations Свойство отображаемого имени для поля

using System.ComponentModel.DataAnnotations; 
public class DCArrival : IDCArrival 
{ 
    [Display(Name = "Via Transit")] 
    public String LocationType { get; set; } 
    [Display(Name = "Currency")] 
    String CurrencyISOCode { get; } 
} 

Тогда я хочу, чтобы использовать эту DisplayName, когда я создаю строку заголовка. Марк псевдокод, что tryes, чтобы объяснить, что я хочу, чтобы разжиться:

private MemoryStream CreateExcelFile(ICollection<DCArrival> dcArrToShow 
, QueryStrInput queryStrInput) 
    { 
     try 
     { 
      // Create an Excel Workbook 
      XLWorkbook wb = new XLWorkbook(); 
      // Add the worksheet with data 
      IXLWorksheet ws = wb.Worksheets.Add("New Worksheet"); 
      // Add my data that was displayed in the html table ... 
      ws.Cell(1, 1).SetValue("Hello World"); 
      //Add Header row. By taking a object in the collection and figure out its 
      // display name 
      DCArrival firstRow = dcArrToShow.First(); 
      // Here comes my problem. Here is my dream up mockup code 

      ws.Cell(2,1).Value = firstRow.LocationType.DisplayAttribute.GetName() 
      ws.Cell(2,2).Value = firstRow.CurrencyISOCode.DisplayAttribute.GetName() 
      // back to reality 
      //this is how easy I can get all data from Collection 
      ws.Cell(3, 1).Value = dcArrToShow.AsEnumerable(); 
      // All done 
      MemoryStream ms = new MemoryStream(); 
      wb.SaveAs(ms); 
      return ms; 
     } 
     catch (Exception e) 
     { 
      string errmsg = String.Format("Failed to create Excel file: {0}", 
      e.Message); 
      throw new Exception(errmsg, e); 
     } 

Я посмотрел на http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.displayattribute.aspx Но я не понимаю, как я ухватить его. Я понимаю, что это волшебство исправлено для вас, когда вы используете обычный рендеринг mvc 3 html. Когда я нагуглить эти понятия я утонуть в блогах, кто хочет, чтобы объяснить основные проверки в MVC 3.

+0

смотрите по этой ссылке [Как я могу получить доступ к DisplayName данных значений аннотаций фр Код ом] [1] [1]: http://stackoverflow.com/questions/3485737/how-can-i-access-the-displayname-data-annotation-value-from-code – MikMark

ответ

3

Вы можете извлечь его из метаданных модели:

ws.Cell(2.1).Value = ModelMetadata.FromLambdaExpression<DCArrival, string>(x => x.LocationType, new ViewDataDictionary<DCArrival>(firstRow)).DisplayName; 

или написать метод расширения:

public static class ModelMetadataExtensions 
{ 
    public static string GetName<TModel, TProperty>(this TModel model, Expression<Func<TModel, TProperty>> ex) 
    { 
     return ModelMetadata 
      .FromLambdaExpression<TModel, TProperty>(ex, new ViewDataDictionary<TModel>(model)) 
      .DisplayName; 
    } 
} 

, а затем:

ws.Cell(2.1).Value = firstRow.GetName(x => x.LocationType); 
ws.Cell(2.2).Value = firstRow.GetName(x => x.CurrencyISOCode); 

UPDATE:

В соответствии с новым требованием, которое было выражено в разделе комментариев, чтобы перебрать все свойства и прочитать дисплей атрибута можно использовать следующие:

var properties = typeof(DCArrival).GetProperties(); 
foreach (var property in properties) 
{ 
    var displayAttribute = property 
     .GetCustomAttributes(typeof(DisplayAttribute), true) 
     .FirstOrDefault() as DisplayAttribute; 
    string displayName = property.Name; 
    if (displayAttribute != null) 
    { 
     displayName = displayAttribute.Name; 
    } 

    // TODO: do something with the display name for this property 
} 
+0

Я не понимаю (первое значение), но: ws.Cell (2,1) .Value = ModelMetadata.FromLambdaExpression (x => x.LocationType, new ViewDataDictionary ()). DisplayName; работал нормально. Спасибо –

+0

@ PatrikLindström, это была опечатка. Это должно быть 'firstRow'. Я исправил это. –

+0

Что делать, если я хотел бы разработать и хотел бы перебрать всех членов моего DCArrival. Я попробовал это, но тогда DisplayName всегда равно null. Тип type = typeof (DCArrival); PropertyInfo [] properties = type.GetProperties(); foreach (свойство PropertyInfo в свойствах) { строка displayName = ModelMetadata.FromLambdaExpression (x => property.Имя, новый ViewDataDictionary (firstRow)). DisplayName; ws.Cell (startRow, j ++). Value = displayName; } –

1

Вы, ребята делают это неправильно ...

static void Main() 
{ 

    var wb = new XLWorkbook(); 
    var ws = wb.Worksheets.Add("People"); 

    var people = new List<Person> 
    { 
     new Person{Name = "John Doe", DOB = new DateTime(1980,1,1)}, 
     new Person{Name = "Jane Doe", DOB = new DateTime(1985,1,1)} 
    }; 

    ws.FirstCell().InsertTable(people); 

    ws.Columns().AdjustToContents(); 
    wb.SaveAs(@"C:\MyFiles\Excel Files\Sandbox.xlsx"); 
} 

class Person 
{ 
    [Display(Name = "Person's Name")] 
    public String Name { get; set; } 

    [Display(Name = "Date of Birth")] 
    public DateTime DOB { get; set; } 
} 

enter image description here

+0

Да, я вижу, что я пропустил этот бит документации по адресу closedxml http://closedxml.codeplex.com/wikipage?title=Inserting%20Tables&referringTitle=Documentation Отлично, теперь у меня есть полный контроль над CustomAttributes. благодаря –

Смежные вопросы