Самозакрывающийся HTML Общий контроль?

Я пишу немного кода, чтобы добавить тег ссылки к тегу head в коде позади... т.е.

HtmlGenericControl css = new HtmlGenericControl("link");

css.Attributes["rel"] = "Stylesheet";
css.Attributes["type"] = "text/css";
css.Attributes["href"] = String.Format("/Assets/CSS/{0}", cssFile);

попытаться достичь чего-то вроде...

<link rel="Stylesheet" type="text/css" href="/CSS/Blah.css" />

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

<link rel="Stylesheet" type="text/css" href="/CSS/Blah.css"></link>

Я не могу найти то, что мне не хватает, чтобы не сделать дополнительные </link>Я предположил, что это должно быть свойство объекта.

Я что-то упустил или это просто невозможно с этим контролем?

Спасибо

5 ответов

Решение

Я думаю, что вы должны извлечь из HtmlGenericControlи переопределить Render метод.

Затем вы сможете написать "/>" самостоятельно (или вы можете использовать HtmlTextWriter's SelfClosingTagEnd константа).

Изменить: вот пример (в VB)

Пытаясь написать обходной путь для umbraco.library:RegisterStyleSheetFile(string key, string url) Я закончил тем же вопросом, что и ОП, и обнаружил следующее.

Согласно спецификации, тег ссылки является пустым элементом. Он не может иметь никакого содержания, но может быть самозакрывающимся. Валидатор W3C не проверял <link></link> как правильно html5.

По-видимому

HtmlGenericControl css = new HtmlGenericControl("link");

по умолчанию отображается как <link></link>, Использование специального элемента управления для тега ссылки решило мою проблему:

HtmlLink css = new HtmlLink();

Производит наценку <link/> который был подтвержден как правильный xhtml и html5.

В дополнение к ссылке, System.Web.UI.HtmlControls содержит классы для других элементов управления void, таких как img, input и meta.

В качестве альтернативы вы можете использовать Page.ParseControl(string), который дает вам элемент управления с тем же содержимым, что и передаваемая вами строка.

Я фактически делаю то же самое в моем текущем проекте. Конечно, это требует ссылки на текущую страницу (обработчик), но это не должно создавать никаких проблем.

Единственное предостережение в этом методе, на мой взгляд, заключается в том, что вы не получаете никакого "ОО" подхода для создания вашего элемента управления (например, control.Attributes.Add("href", theValue") так далее.)

Немного хакерский способ.

  • Поместите элемент управления в элемент PlaceHolder.
  • В коде за угон метода рендеринга PlaceHolder.
  • Визуализируйте содержимое PlaceHolders точно так, как вы хотите.

Это зависит от страницы / элемента управления и не требует переопределений. Так что это оказывает минимальное влияние на остальную часть вашей системы.

<asp:PlaceHolder ID="myPlaceHolder" runat="server">
    <hr id="someElement" runat="server" />
</asp:PlaceHolder>

protected void Page_Init(object sender, EventArgs e)
{
    myPlaceHolder.SetRenderMethodDelegate(ClosingRenderMethod);
}

protected void ClosingRenderMethod(HtmlTextWriter output, Control container)
{
    var voidTags = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase) { "br", "hr", "link", "img" };
    foreach (Control child in container.Controls)
    {
        var generic = child as HtmlGenericControl;
        if (generic != null && voidTags.Contains(generic.TagName))
        {                
            output.WriteBeginTag(generic.TagName);
            output.WriteAttribute("id", generic.ClientID);
            generic.Attributes.Render(output);
            output.Write(HtmlTextWriter.SelfClosingTagEnd);                
        }
        else
        {
            child.RenderControl(output);
        }
    }
}

Я только что создал решение для этого, основываясь на комментариях Ragaraths на другом форуме:

http://forums.asp.net/p/1537143/3737667.aspx

Переопределите HtmlGenericControl с этим

protected override void Render(HtmlTextWriter writer)
{
    if (this.Controls.Count > 0)
        base.Render(writer); // render in normal way
    else
    {
        writer.Write(HtmlTextWriter.TagLeftChar + this.TagName); // render opening tag
        Attributes.Render(writer); // Add the attributes.  
        writer.Write(HtmlTextWriter.SelfClosingTagEnd); // render closing tag   
    }

    writer.Write(Environment.NewLine); // make it one per line
}
Другие вопросы по тегам