2016-02-09 6 views
2

Я хотел бы создать HtmlHelper, который можно использовать в свойствах IEnumerable.Могу ли я создать HtmlHelper специально для свойств IEnumerable?

Цель состоит в том, чтобы использовать его как это:

@Html.DisplayForEnumerable(m => m.EnumerableItemsProperty, "ViewTemplateName"); 

Если это возможно, я хотел бы использовать синтаксис m => m.Items лямбда (в отличие от прохождения через Model.Items).

Это мое лучшее усилие. Но я не уверен, как получить переменную items из параметра выражения.

Я подозреваю, что, возможно, мне нужно использовать что-то вроде IEnumerable<TValue> в качестве возвращаемого типа выражения, но я совершенно новичок в дженериках, и я не знаю, как это реализовать.

public static MvcHtmlString DisplayForEnumerable<TModel>(this HtmlHelper<TModel> html, Expression<Func<TModel, IEnumerable>> expression, string templateName, object additonalViewData = null) 
{ 
    var sb = new StringBuilder(); 

    // how to get items variable? 

    foreach (var item in items) 
    { 
     var item1 = item; 
     sb.Append(html.DisplayFor(m => item1, templateName, additonalViewData)); 
    } 

    return MvcHtmlString.Create(sb.ToString()); 
} 

Update

Для уточнения - я беру этот подход, потому что я хотел бы иметь возможность так указать различные шаблоны для одной и той же модели. И нормальная нумерация DisplayFor() не возникает, если вы укажете конкретный шаблон.

Я знаю, что могу просто перечислить вручную, но я бы предпочел использовать этот метод, если только кто-то более осведомленный не советует иначе.

+0

MVC уже имеет это. Его просто '@ Html.DisplayFor (m => m.EnumerableItemsProperty)' и вы создаете 'EditorTemplate' для типа, который используется в вашей коллекции. –

+0

Спасибо, Стивен. Я хотел бы иметь возможность использовать различные шаблоны, если это возможно, и автоматическое перечисление не происходит, если вы укажете конкретный шаблон. Я знаю, что могу просто перечислить вручную, но я подумал об этом так. Не могли бы вы посоветовать это? –

+0

Не уверен, что вы имеете в виду. Если у вас есть модель say 'Person.cs', тогда вы создаете' EditorTemplate' - '/ View/Shared/EditorTemplates/Person.cshtml', тогда метод' DisplayFor() 'генерирует правильный html для каждого' Person' в Коллекция. Если вам нужны разные шаблоны, связанные с разными контроллерами, вы можете поместить их в папки '/ Views/yourControllerName/EditorTemplates' –

ответ

1

Вы помощник должен быть

public static MvcHtmlString DisplayForEnumerable<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, string templateName, object additionalViewData = null) 
{ 
    ModelMetadata metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData); 
    IEnumerable collection = metaData.Model as IEnumerable; 
    if (collection == null) 
    { 
     return helper.DisplayFor(expression, templateName, additionalViewData); 
    } 
    StringBuilder html = new StringBuilder(); 
    foreach (var item in collection) 
    { 
     html.Append(helper.DisplayFor(m => item, templateName, additionalViewData).ToString()); 
    } 
    return MvcHtmlString.Create(html.ToString()); 
} 

Примечания код позволяют передавать либо один T или IEnumerable<T> (хотя название метода в настоящее время на самом деле не имеет смысла). Если вы хотите, чтобы ограничить его только IEnumerable<T> вы могли бросить InvalidCastException если collection == null

Обратите внимание, что этот подход не будет работать, если вы хотите, чтобы генерировать элементы формы для сбора (например EditorForEnumerable() метода), так как необходимые индексаторы коллекции не добавляются в атрибуты генерации name. Лучший подход заключается в использовании встроенного DisplayFor() и EditorFor() методы, которые будут генерировать правильный HTML для обоих T и IEnemerable<T>

Предполагая, что у вас есть Person.cs класс, создать частичный вид в /Views/Shared/DisplayTemplates/Person.cshtml (обратите внимание на имя файла должно совпадать с именем класса) и с точки зрения просто использовать

@Html.DisplayFor(m => m.yourCollectionProperty) 

Вы также можете создавать специальные отображения и редактор шаблонов для каждого контроллера, например /Views/yourControllerName/DisplayTemplates/Person.cshtml. Это позволяет использовать один шаблон в /Persons/Index и другой шаблон в /Organisation/Details/1, который может отображать список Person, связанный с Organisation

И, наконец, если вам нужны 2 различные шаблоны для Person в том же контроллере, вы можете использовать вид модели, например class PersonVM и class AssociatedPersonVM, и создать EditorTemplate для каждого

+0

Это модельный ответ, много информации - благодаря миллиону. –

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

  • Нет связанных вопросов^_^