代码之家  ›  专栏  ›  技术社区  ›  awrigley

为Razor调整自定义HTML助手(它使用htmltextWriter,因此返回void)

  •  3
  • awrigley  · 技术社区  · 15 年前

    问题

    我有一个非常漂亮的菜单HTML助手为WebFormViewEngine视图编写。此引擎允许您的助手返回void,并且仍然可以使用:

    @Html.Theseus
    

    这对我的助手来说很好,因为它可以使用htmltextwriter呈现菜单,直接呈现到输出流。

    然而,在Razor视图中,HTML助手将返回一个值(通常是mvchtmlstring),这是添加到输出中的值。差别小,后果大。

    有一种方法可以解决这个问题,正如GVS向我指出的(见 ASP.NET MVC 2 to MVC 3: Custom Html Helpers in Razor )如下:

    如果助手返回void,则执行以下操作:

    @{Html.Theseus;}
    

    (本质上,您只是调用方法,而不是渲染到视图中)。

    虽然仍然很整洁,但这与@html.thesus不太一样。所以…

    我的代码很复杂,但工作得很好,所以我不愿意进行主要的编辑,即用另一个编写器替换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();
              }
        }
    

    与TagBuilders一起重新编写不会很有趣。现在,它呈现任何类型的菜单,包括“增量导航”,如我的4guysfromrolla文章中所述: Implementing Incremental Navigation with ASP.NET

    选项:

    我想我可以返回一个空的mvchtmlstring,但这几乎是黑客的定义…

    唯一的选择是进入日落,使用TagBuilder重写助手来构建每个标记,将其添加到StringBuilder,然后构建下一个标记,等等,然后使用StringBuilder实例来创建mvchtmlstring。真的很难看,除非我能做些像…

    问题:

    有没有办法:

    停止呈现到流中的htmltextwriter,而是像使用StringBuilder一样使用它,在我用于创建mvchtmlstring(或htmlstring)的进程结束时使用它?

    听起来不太可能,即使我在写…

    PS:

    关于htmltextWriter,最大的好处是可以构建大量的标记,而不是像使用标记生成器那样一个接一个地构建它们。

    1 回复  |  直到 15 年前
        1
  •  7
  •   Community Mohan Dere    9 年前

    other question similar question

    public static void Theseus(this HtmlHelper html)
    {
        var writer = new HtmlTextWriter(html.ViewContext.Writer);
        ...
    }
    

    Html.Partial Html.RenderPartial

    <%: Html.Partial("Name") %>
    <% Html.RenderPartial("Name") %>
    

    @Html.Partial("Name")
    @{ Html.RenderPartial("Name"); }
    

    @Html.Theseus()

    public static IHtmlString Theseus(this HtmlHelper html)
    {
        var writer = new HtmlTextWriter(html.ViewContext.Writer);
        ...
        return new HtmlString("");
    }