MVC 3 Razor,自定义标记/部分的助手

时间:2012-01-31 22:13:18

标签: asp.net-mvc-3 razor html-helper

我甚至不确定这是否可行,但我想我会检查是否有办法让这更容易。

首先,我的网站中有一些重复的标记,如下所示:

<div class="module">
    <h3>Title</h3>
    <div>
        <p>Information goes here</p>
    </div>
</div>

我想要做的是将它包装在某种帮助器/部分中,以便我可以做这样的事情

@MyHelper("This is my Title") {
    <p>Here is my custom markup</p>
}

然后,当它呈现时,它将注入通过<h3></h3>和div中的自定义标记之间的参数传入的标题。自定义标记可以是从测试,表单控件到局部视图的任何内容。这是可能的吗?

4 个答案:

答案 0 :(得分:15)

还有另一种方式,没有一次性技巧,这也需要少一点工作,非常适合小帮手。

@helper MyHelper(string title, Func<object, object> markup) {
    <div class="module">
        <h3>Title</h3>
        <div>
            <p>@markup.DynamicInvoke(this.ViewContext)</p>
        </div>
    </div>
}

这个助手的用法如下:

@MyHelper("This is my Title", 
    @<p>Here is my custom markup</p>
)

或多行:

@MyHelper("This is my Title", 
    @<text>
        <p>More than one line</p>
        <p>Of markup</p>
    </text>
)

Telerik MVC控件使用这个技巧,例如让你在文档加载时添加你的javascript代码。

这里也是一个不错的example。还有一些信息here

答案 1 :(得分:12)

嗯,这是使用HTML帮助扩展程序做一些接近它的“标准”方法。 Html.BeginForm()所做的一个非常简单的版本。

方法:只需返回一个IDisposable,让using语句处理其余的事情。

这只是概念的一个例子(尽管它有效)。不打算立即重复使用。使用大量快捷方式快速编写,而不是生产代码,大量改进和优化的机会,可能有愚蠢的错误,可以使用TagBuilder等。可以轻松修改以重用Wrapper类用于不同的...包装(甚至可能是一个已经在ASP.NET MVC中的通用 - 没有一个需要)。

public static class WrapHelper
{
    private class Wrapper : IDisposable
    {
        private bool disposed;
        private readonly TextWriter writer;

        public Wrapper(HtmlHelper html)
        {
            this.writer = html.ViewContext.Writer;
        }

        public void Dispose()
        {
            if (disposed) return;

            disposed = true;

            writer.WriteLine("  </div>");
            writer.WriteLine("</div>");
        }
    }

    public static IDisposable Wrap(this HtmlHelper html, string title)
    {
        TextWriter writer = html.ViewContext.Writer;

        writer.WriteLine("<div class=\"module\">");
        writer.WriteLine("  <h3>" + html.Encode(title) + "</h3>");
        writer.WriteLine("  <div>");

        return new Wrapper(html);
    }
}

用法:

@using (Html.Wrap("Title"))
{
    <p>My very own markup.</p>
}

答案 2 :(得分:3)

@TheKaneda,感谢您的见解。我接受了你的想法并将其扩展,以便你提供一个PartialView名称,它知道如何解析它。

<Extension()> _
Public Function UseTemplate(ByVal html As HtmlHelper, ByVal PartialView As String) As IDisposable
    Return New TemplateWrapper(html, PartialView)
End Function

Public Class TemplateWrapper
    Implements IDisposable

    Private _HtmlHelper As HtmlHelper

    'Index 0 is header
    'Index 1 is footer
    Private _TemplateWrapper As String()

    Public Sub New(ByVal Html As HtmlHelper, ByVal PartialView As String)

        _TemplateWrapper = Html.Partial(PartialView).ToHtmlString.Split("@@RenderBody()")

        _HtmlHelper = Html
        _HtmlHelper.ViewContext.Writer.Write(_TemplateWrapper(0))

    End Sub

    Public Sub Dispose() Implements IDisposable.Dispose

        _HtmlHelper.ViewContext.Writer.Write(_TemplateWrapper(1).Substring(12))

    End Sub

End Class

使用与@ TheKaneda相同的用法。在部分视图中,不要调用@RenderBody(),只需将@@ RenderBody()作为内容中间部分的标志。对不起VB翻译。

使用我的用法示例。

Using Html.UseTemplate("ContentWrapper")

    @Html.EditorFor(Function(m) m.Var1, "TemplateHint")
    @Html.EditorFor(Function(m) m.Var2, "TemplateHint")
    @Html.EditorFor(Function(m) m.Var3)

End Using

My Partial看起来像这样......

<div class="content"> 
    @@RenderBody()
</div>

答案 3 :(得分:0)

如果您正在使用Razor和MVC 3,那么编写一个快速帮助方法就可以很容易地进入app_code文件夹,(我将其命名为MyHtmlHelpers)

我会尝试一些不同的东西,例如:

@helper myTemplate(string title, string markup){
    <div class="module">
        <h3>@title</h3>
        @markup
    </div>
}

从.cshtml文件中使用它的方式如下:

@MyHtmlHelpers.myTemplate('title','markup')

如果我理解正确,它应该有效。