Создание MVC3 Razor Helper как Helper.BeginForm () - PullRequest
22 голосов
/ 25 августа 2011

Я хочу создать помощника, который я могу добавить содержимое в скобках, как это делает 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" - это идентификатор css для этого div, а "title" - это заголовок раздела.

Есть ли лучший способчтобы достичь этого, кроме как делать то, что я пытаюсь сделать?

заранее спасибо за любую помощь.

Ответы [ 2 ]

36 голосов
/ 26 августа 2011

Это вполне возможно. То, как это делается в MVC с такими вещами, как Helper.BeginForm, заключается в том, что функция должна возвращать объект, который реализует IDisposable.

Интерфейс IDisposable определяет один метод с именем Dispose, который вызывается непосредственно перед сборкой мусора.

В C # ключевое слово using полезно для ограничения области видимости объекта и для сбора мусора, как только он выходит из области видимости. Таким образом, использование его с IDisposable естественно.

Вы захотите реализовать класс Section, который реализует IDisposable. Он должен будет визуализировать открытый тег для вашего раздела, когда он будет создан, и визуализировать закрывающий тег, когда он будет удален. Например:

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>");
    }
}

Теперь, когда тип доступен, вы можете расширить HtmlHelper.

public static MySection BeginSection(this HtmlHelper self, string className, string title) {
    return new MySection(self, className, title);
}
4 голосов
/ 10 ноября 2014

Вот небольшая утилита, которую я написал, чтобы сделать это. Он немного более универсален, поэтому вы можете использовать его для любого тега и с любыми атрибутами. Он настроен как метод расширения в 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));
        }
    }
}
...