问题
我有一个为 WebFormViewEngine 视图编写的非常漂亮的菜单 Html 帮助器。该引擎允许您的助手返回 void,但仍然能够使用:
@Html.Theseus
这对我的助手来说非常有用,因为它可以使用 HtmlTextWriter 渲染菜单,直接渲染到输出流。
然而,在 Razor 视图中,Html 帮助程序应返回一个值(通常是 MvcHtmlString),该值将添加到输出中。小差异,大后果。
正如 GvS 向我指出的那样,有一种解决方法(请参阅ASP.NET MVC 2 到 MVC 3:Razor 中的自定义 Html 帮助程序) 如下:
如果助手返回 void,则执行以下操作:
@{Html.Theseus;}
(本质上,您只是调用该方法,而不是渲染到视图中)。
虽然仍然很简洁,但这与@Html.Theseus 不太一样。所以...
我的代码很复杂,但工作得很好,所以我不愿意进行重大编辑,即用另一个编写器替换 HtmlTextWriter。代码片段如下:
writer.AddAttribute(HtmlTextWriterAttribute.Href, n.Url);
writer.AddAttribute(HtmlTextWriterAttribute.Title, n.Description);
writer.RenderBeginTag(HtmlTextWriterTag.A);
writer.WriteEncodedText(n.Title);
writer.RenderEndTag();
// Recursion, if any
// Snip off the recursion at this level if specified by depth
// Use a negative value for depth if you want to render the entire sitemap from the starting node
if ((currentDepth < depth) || (depth < 0))
{
if (hasChildNodes)
{
// Recursive building starts here
// Open new ul tag for the child nodes
// "<ul class='ChildNodesContainer {0} Level{1}'>";
writer.AddAttribute(HtmlTextWriterAttribute.Class, "Level" + currentDepth.ToString());
writer.RenderBeginTag(HtmlTextWriterTag.Ul);
// BuildMenuLevel calls itself here to
// recursively traverse the sitemap hierarchy,
// building the menu as I go.
// Note: this is where I increase the currentDepth variable!
BuildChildMenu(currentDepth + 1, depth, n, writer);
// Close ul tag for the child nodes
writer.RenderEndTag();
}
}
用 TagBuilder 重新编写不会很有趣。就目前情况而言,它呈现任何类型的菜单,包括我的 4guysfromrolla 文章中描述的“增量导航”:使用 ASP.NET 实现增量导航
选项:
我想我可以返回一个空的 MvcHtmlString,但这几乎是黑客的定义......
唯一的选择是日落时分,使用 TagBuilder 重写帮助器来构建每个标签,将其添加到 StringBuilder,然后构建下一个标签,等等,然后使用 StringBuilder 实例创建 MvcHtmlString。真的很难看,除非我能做类似的事情......
问题:
有没有办法:
停止 HtmlTextWriter 渲染到流,而是像 StringBuilder 一样使用它,在我用来创建 MvcHtmlString (或 HtmlString)的过程结束时?
听起来不太可能,即使在我写的时候……
PS:
HtmlTextWriter 的伟大之处在于您可以构建大量标签,而不是像使用 TagBuilder 那样一个接一个地构建它们。