Вложенный TagBuilder - как TagBuilderTree-

TagBuilder — хорошая реализация для создания HTML-элементов. Но -некоторые-элементы HTML могут иметь другие элементы (я назвал их дочерними). Я не смог найти ни одного класса из классов Mvc.

Вопрос; Должен ли я реализовать несколько классов (TagBuilderTree и TagBuilderNode), поддерживающих вложенные теги, или я что-то упустил?


person Nuri YILMAZ    schedule 10.02.2011    source источник


Ответы (3)


Вы можете создать дочерние элементы в отдельных конструкторах тегов и поместить созданный ими HTML-код в родительский конструктор тегов.

Вот пример: <select> с некоторыми <option> (пример обезжирен для краткости)

TagBuilder select = new TagBuilder("select");  

foreach (var language in languages) // never ye mind about languages
{
    TagBuilder option = new TagBuilder("option");
    option.MergeAttribute("value", language.ID.ToString());

    if (language.IsCurrent)
    {
        option.MergeAttribute("selected", "selected");
    }

    option.InnerHtml = language.Description;
    // And now, the money-code:
    select.InnerHtml += option.ToString();
}
person SLaks    schedule 10.02.2011
comment
Я предпочитаю реализовывать TagBuilderTree и TagBuilderNode, они будут инкапсулировать вложенные теги для наших проектов, но я пытаюсь найти ответ, почему Razor их не обслуживает? Потому что это похоже на необходимость для всех пользователей Razor. - person Nuri YILMAZ; 10.02.2011
comment
Вы имеете в виду веб-страницы, а не Razor. Это не обязательно для всех разработчиков; вместо этого вы можете использовать статические помощники. - person SLaks; 10.02.2011
comment
вы правы, я говорю о классе System.Web.Mvc.TagBuilder. Это не имеет прямого отношения к движку Razor. Его могут использовать все движки. Мне интересно, почему у нас нет TagBuilder в виде дерева, и должен ли я использовать TagBuilder для вложенных тегов html. Или мне следует реализовать свои собственные классы TagBuilderTree и TagBuilderNode? - person Nuri YILMAZ; 10.02.2011
comment
Вкладывая конструкторы тегов, вы существенно снижаете производительность внутренне используемого класса StringBuilder, верно? - person Michiel Cornille; 07.06.2012
comment
@Mvision: Правильно. Если теги могут быть длинными, XElement, вероятно, будет быстрее. - person SLaks; 07.06.2012
comment
Я добавил пример, надеюсь, что все в порядке. - person MrBoJangles; 23.02.2013
comment
@MrBoJangles: StringBuilder было бы более эффективно. - person SLaks; 24.02.2013
comment
Хорошо знать. Это пример кода, который создает один <select> максимум с полдюжиной опций, поэтому улучшенная читабельность для меня важнее. Полноценная древовидная структура может быть больше связана с производительностью. Если кто-то захочет добавить пример StringBuilder, было бы неплохо сравнить/сопоставить. - person MrBoJangles; 25.02.2013

Хорошо, я решил провести небольшой тест в своей собственной кодовой базе.

Я сравнил эти два метода, чтобы создать точно такой же окончательный HTML:

  1. Генерация html вручную с помощью StringBuilder
  2. Использование нескольких TagBuilders и вложение контента

Генерация html вручную с помощью StringBuilder:


    var sb = new StringBuilder();
    sb.AppendLine("<div class='control-group'>");
    sb.AppendFormat(" <label class='control-label' for='{0}_{1}'>{2}</label>", propObj.ModelType, propObj.ModelProperty, propObj.LabelCaption);
    sb.AppendLine("  <div class='controls'>");
    sb.AppendFormat("    <input id='{0}_{1}' name='{0}[{1}]' value='{2}' />", propObj.ModelType, propObj.ModelProperty, propObj.PropertyValue);
    sb.AppendLine("  </div>");
    sb.AppendLine("</div>");

    return new HtmlString(sb.ToString());

Использование нескольких TagBuilders и объединение контента:


    TagBuilder controlGroup = new TagBuilder("div");
    controlGroup.AddCssClass("control-group");

    TagBuilder label = new TagBuilder("label");
    label.AddCssClass("control-label");
    label.InnerHtml = propObj.LabelCaption;

    TagBuilder controls = new TagBuilder("div"); 

    TagBuilder input = new TagBuilder("input");
    input.Attributes["id"] = propObj.ModelType + "_" + propObj.ModelProperty;
    input.Attributes["name"] = propObj.ModelType + "[" + propObj.ModelProperty + "]";
    input.Attributes["value"] = propObj.PropertyValue;

    controls.InnerHtml += input;

    controlGroup.InnerHtml += label;
    controlGroup.InnerHtml += controls;

    return new HtmlString(controlGroup.ToString());

На мой взгляд, № 1 легче читать и он более лаконичен, но я также могу оценить структуру № 2.

person MattSlay    schedule 12.12.2012
comment
# 1 также является возможным путем для внедрения скриптов, если вы не будете тщательно очищать, я просто хотел бы добавить. - person Bon; 10.07.2014
comment
Я думаю, что № 1 более подвержен ошибкам, потому что он основан на правильном вводе HTML с правильным размещением закрывающих тегов, одинарных кавычек, двойных кавычек и т. Д. Кроме того, TagBuilder имеет больше интеллекта. Например, при добавлении класса CSS stringbuilder не будет предоставлять никакого интеллекта для добавления класса, тогда как TagBulder имеет метод AddCSSClass, который имеет интеллект. Также я нахожу № 2 гораздо более читаемым. Все заполнители в методе №1 делают вещи менее ясными. - person Louise Eggleton; 18.08.2014

Проблема, с которой я столкнулся при создании тегов TagBuilder, заключается в том, что он выглядит очень неудобным в сопровождении. С другой стороны, AppendFormat StringBuilder не только делает код удобным в сопровождении, но и работает с хорошей эффективностью.

Я немного улучшил метод MattSlay №1. Я использовал только один вызов метода AppendFormat StringBuilder и использовал строковый литерал C# для определения формата. В результате формат выглядит точно так же, как и желаемый результат, и работает эффективно.

var sb = new StringBuilder();
    sb.AppendFormat(
     @"<div class='control-group'>
          <label class='control-label' for='{0}_{1}'>{2}</label>
          <div class='controls'>
             <input id='{0}_{1}' name='{0}[{1}]' value='{3}' />
          </div>
      </div>",
      propObj.ModelType,
      propObj.ModelProperty,
      propObj.LabelCaption,
      propObj.PropertyValue);

    return new HtmlString(sb.ToString());

Надеюсь это поможет!

person Salman Hasrat Khan    schedule 13.08.2013
comment
это был старый вопрос. каковы ваши классы изменения предложения как «контрольная метка». все они жестко закодированы как классические страницы asp (не asp.net). я всегда думаю, что обслуживание важнее, чем код. - person Nuri YILMAZ; 13.08.2013
comment
Похоже, это не сработает, поскольку значение ввода будет установлено в заголовок метки. Обратите внимание, что версия MattSlay использует два разных списка параметров. Вы можете избавиться от копий ModelType и ModelProperty и получить доступ к PropertyValue как {3} - person Robert; 31.12.2013
comment
@Robert Я просто пытался продемонстрировать, что вы можете получить эффективность TagBuilder и удобство сопровождения кода, используя один вызов AppendFormat вместо нескольких вызовов AppendFormat, таких как MattSlay. В дополнение к одному вызову AppendFormat обратите внимание, как литерал String в C# позволяет определить строку, отформатированную с пробелами для удобства чтения. Опять же, я просто пытался улучшить метод MattSlay :) - person Salman Hasrat Khan; 02.01.2014
comment
Нет, я согласен с вами, что это очень чисто, просто говорю, что в настоящее время значение ввода установлено в текст метки. - person Robert; 02.01.2014
comment
Ах! Я понимаю, что вы имеете в виду, нет. Даже у Мэтта Слея была точно такая же ошибка, так как я просто скопировал его и улучшил, я не заметил изменения... Я это исправлю. - person Salman Hasrat Khan; 03.01.2014