Самозакрывающийся 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
}