Подтвердить что ты не робот

Создание помощника Razor MVC3 как Helper.BeginForm()

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

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

заблаговременно за помощь.

4b9b3361

Ответ 1

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

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

В С# ключевое слово 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);
}

Ответ 2

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