Добавление атрибутов htmlAttributes в шаблон

#asp.net-mvc-3 #razor #html-helper #asp.net-mvc-templates

#asp.net-mvc-3 #razor #html-помощник #asp.net-mvc-templates

Вопрос:

Если я передаю атрибуты htmlAttributes в шаблон, например:

 @Html.DisplayFor(m => m.FirstName, new { htmlAttributes = new { @class = "orangetxt strongtxt" } })
  

В моем шаблоне, как бы я вставил их в свой HTML:

 <span @ViewData["htmlAttributes"]>@Model</span>
  

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

Я понимаю, что могу выполнить это с помощью метода расширения HtmlHelper для отображения полного элемента HTML (в данном случае span) и передачи атрибутов таким образом, но есть ли способ просто отобразить атрибуты прямо в элементе HTML, как в приведенном выше примере?

Ответ №1:

Приведенный ниже метод расширения позволит мне преобразовать атрибуты htmlAttributes в строку:

     public static MvcHtmlString RenderHtmlAttributes<TModel>(
        this HtmlHelper<TModel> htmlHelper, object htmlAttributes)
    {
        var attrbituesDictionary = new RouteValueDictionary(htmlAttributes);

        return MvcHtmlString.Create(String.Join(" ", 
            attrbituesDictionary.Select(
                item => String.Format("{0}="{1}"", item.Key, 
                htmlHelper.Encode(item.Value)))));
    }
  

Затем, чтобы отобразить их в теге, я могу просто сделать это:

 <span @Html.RenderHtmlAttributes(ViewData["htmlAttributes"])>@Model</span>
  

Комментарии:

1. Хм, возможно, я здесь ошибаюсь, но мне кажется, что ваше предполагаемое использование, основанное на вопросе, не сработает .. возможно, вы можете указать, как вы используете помощника

Ответ №2:

Ответ Джерада Роуза хороший, но я столкнулся с парой проблем с ним:

  • Он не преобразует символы подчеркивания в тире в именах атрибутов
  • Он не обрабатывает атрибуты, не имеющие значения, корректно

Чтобы решить первую проблему, используйте HtmlHelper.AnonymousObjectToHtmlAttributes .

Ниже приведена моя модификация метода Джерада:

 public static MvcHtmlString RenderHtmlAttributes(this HtmlHelper helper, object htmlAttributes)
{
        if (htmlAttributes == null) return new MvcHtmlString(String.Empty);
        var attrbituesDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
        return new MvcHtmlString(String.Join(" ", attrbituesDictionary.Select(item => string.IsNullOrEmpty((string)item.Value) ? String.Format("{0}", item.Key) : String.Format("{0}="{1}"", item.Key, helper.Encode(item.Value)))));
}
  

Ответ №3:

Попробуйте это вместо,

 @Html.DisplayFor(m => m.FirstName, 
                 new { htmlAttributes = "class = orangetxt strongtxt"})
  

Это приведет к отображению строки, в то время как ваша версия делала странные вещи, отображаемые { } как часть вывода.

Комментарии:

1. Это близко, но все же не совсем то, что я ищу. Я действительно не хочу иметь дело со всеми преобразованиями и кодировками строк. На самом деле я придумал метод расширения для отображения атрибутов HTML и опубликую его ниже.

2. @JeradRose — в зависимости от того, что у вас есть, ничего не меняется, кроме фактического вызова Displayfor, поэтому никаких преобразований и кодирования

3. Да, но выше был только пример. У меня могут быть случаи, когда атрибуты должны быть немного более сложными и требовать кавычек. Например, если мне нужно включить class = "orangetxt strongtxt" id = "myId" , то использование вашего решения начинает становиться немного сумасшедшим.

4. @JeradRose — справедливо, я не уловил часть об использовании нескольких атрибутов, мой плохой…

Ответ №4:

DisplayFor() используется для отображения шаблона, соответствующего типу свойства.

Шаблоны отображения — это файлы .cshtml внутри папки /DisplayTemplates, которая, в свою очередь, находится внутри папки просмотра (т. Е. Любой папки из домашней, общей или даже определенного контроллера).

Пример.

Если у вас есть шаблон String.cshtml, подобный этому, внутри /Views/Shared:

 @model String

@if (string.IsNullOrEmpty(Model)) {
   <span>(no string)</span>
}
else {
   <span>@Model</span>
}
  

Каждый раз, когда вы вызываете DisplayFor() свойство string:

 DisplayFor(model => model.MyStringProperty);
  

Он отображает шаблон в соответствии со значением строки. Вы можете быть более конкретными и поместить / DisplayTemplates в определенную папку представления, и шаблон влияет только на вызовы из этих представлений.


В вашем случае вы можете быть еще более конкретными и вызывать DisplayFor() с определенным шаблоном.

Предположим, у вас есть шаблон для определенного свойства, называемого MyPropertyTemplate.cshtml. Вы бы назвали DisplayFor() так:

 DisplayFor(model => model.MyProperty, "MyPropertyTemplate");
  

И у них внутри этого шаблона вы можете иметь любые атрибуты HTML, которые вы хотите.

 @model MyProperty

<span class="orangetxt strongtxt">@MyProperty.ToString()</span>
  

PS: Когда он не находит шаблон, я думаю, он вызывает только model.Property.ToString() без дополнительного html.

К вашему сведению: EditorFor() , например, работает аналогичным образом, но использует папку /EditorTemplates .

Комментарии:

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

2. Проблема с шаблонами, Джерад, в том, куда идут атрибуты htmlAttributes? У вас может быть огромный шаблон со многими разделениями, а что нет. То, что вы хотите сделать, будет очень нестандартным, и в основном это включает в себя написание собственных методов HtmlHelper для вывода с помощью пользовательских атрибутов htmlAttributes.

3. Правда, я понимаю, что со сложными шаблонами трудно понять, к чему htmlAttributes они будут применены. В моем случае он всегда будет применяться к элементу, непосредственно окружающему значение модели. Если бы я хотел, скажем, включить другую опцию для применения пользовательских атрибутов к метке, то я мог бы добавить поддержку labelHtmlAttributes , например.