像Helper.BeginForm()一样创建MVC3 Razor Helper

时间:2011-08-25 19:44:59

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

我想创建一个帮助器,我可以像Helper.BeginForm()那样在括号之间添加内容。我不介意为我的助手创建一个Begin,End,但这样做非常简单易行。

基本上我要做的是在这些标签之间包装内容,以便它们呈现为已格式化

类似

@using Html.Section("full", "The Title")
{
This is the content for this section
<p>More content</p>
@Html.TextFor("text","label")
etc etc etc
}

参数“full”是该div的css id,“title”是该部分的标题。

除了做我想做的事情之外,还有更好的方法来实现这个目标吗?

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:36)

这完全有可能。在MVC中使用Helper.BeginForm之类的方式完成此操作的方法是函数必须返回一个实现IDisposable的对象。

IDisposable interface定义了一个名为Dispose的方法,该方法在对象被垃圾收集之前调用。

在C#中,using关键字有助于限制对象的范围,并在它离开范围时立即对其进行垃圾收集。因此,将其与IDisposable一起使用是很自然的。

您需要实现一个实现Section的{​​{1}}类。它必须在构造时为部分渲染开放标记,并在处理时渲染关闭标记。例如:

IDisposable

现在该类型可用,您可以扩展HtmlHelper。

public class MySection : IDisposable {
    protected HtmlHelper _helper;

    public MySection(HtmlHelper helper, string className, string title) {
        _helper = helper;
        _helper.ViewContext.Writer.Write(
            "<div class=\"" + className + "\" title=\"" + title + "\">"
        );
    }

    public void Dispose() {
        _helper.ViewContext.Writer.Write("</div>");
    }
}

答案 1 :(得分:4)

这是我写的一个小工具来做这件事。它更通用,因此您可以将它用于任何标记和任何属性。它被设置为HtmlHelper的扩展方法,因此您可以在Razor内部以及在代码内使用它。

public static class WrapUtil
{
    public static IDisposable BeginWrap(this HtmlHelper helper, string tag, object htmlAttributes)
    {
        var builder = new TagBuilder(tag);
        var attrs = GetAttributes(htmlAttributes);
        if (attrs != null)
        {
            builder.MergeAttributes<string, object>(attrs);
        }
        helper.ViewContext.Writer.Write(builder.ToString(TagRenderMode.StartTag));

        return new WrapSection(helper, builder);
    }

    private static IDictionary<string, object> GetAttributes(object htmlAttributes)
    {
        if (htmlAttributes == null)
        {
            return null;
        }
        var dict = htmlAttributes as IDictionary<string, object>;
        if (dict != null)
        {
            return dict;
        }
        return HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
    }

    private class WrapSection : IDisposable
    {
        private readonly HtmlHelper _Helper;
        private readonly TagBuilder _Tag;

        public WrapSection(HtmlHelper helper, TagBuilder tag)
        {
            _Helper = helper;
            _Tag = tag;
        }

        public void Dispose()
        {
            _Helper.ViewContext.Writer.Write(_Tag.ToString(TagRenderMode.EndTag));
        }
    }
}