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

Создание многократно используемых компонентов HTML-вида с использованием Razor в ASP.NET MVC

У меня есть вспомогательная функция Razor, которая создает повторно используемую HTML-панель, которая позволяет мне писать один и тот же HTML снова и снова.

@helper DefaultPanel(string panelTitle) {
    <div class="panel">
        <div class="panel-logo"><img src="/logo.png"></div>
            <div class=panel-inner">
                <p class="panel-title">@panelTitle</p>
                <div class="panel-content">
                    /* Can I pass content to be rendered in here here? */
                </div>
            </div>
        </div>
    </div>
}

Мне интересно, возможно ли повторное использование этого помощника, чтобы заполнить .panel-content большим количеством HTML, чтобы обеспечить дополнительную гибкость и повторное использование кода - похожее на что-то вроде ниже:

@LayoutHelpers.DefaultPanel("Welcome back") {
    <div class="panel-content-inner">
        <p>Welcome back, please select from the following options</p>
        <a href="#">Profile</a>
        <a href="#">My Defails</a>
    </div>
}

Во время использования .NET MVC я заметил, что Html.BeginForm() делает аналогичную вещь при обертке кода внутри оператора @using в объявлении Html.BeginForm, например:

@using (Html.BeginForm("Index", "Login", FormMethod.Post))
{
    <div>This content gets rendered within the <form></form> markup.</div>
}

Но можно ли это сделать с помощью методов @helper? Если нет, возможно ли создать расширение HtmlHelper для выполнения аналогичной вещи, как это делает метод Html.BeginForm()?

Вы можете сделать очень похожие вещи, используя синтаксис @section, как показано здесь

enter image description here

Это похоже на то, что было бы действительно полезно, чтобы быть в состоянии сделать, и странно, что нет простого способа сделать это на уровне компонентов.

4b9b3361

Ответ 1

Существует два способа достижения требуемой функциональности.

1. @helper

Создайте @helper, который принимает любые параметры, которые вам нужны, плюс функция (параметр одиночного объекта, возвращает объект):

@helper DefaultPanel(string panelTitle, Func<object, object> content)
{
    <div class="panel">
        <div class="panel-logo">
                <img src="/logo.png" />
            </div>
            <div class="panel-inner">
                <p class="panel-title">@panelTitle</p>
                <div class="panel-content">
                    @content(null)
                </div>
            </div>
    </div>
}

Использование:

@DefaultPanel("title",
@<div class="panel-content-inner">
    <p>Welcome back, please select from the following options</p>
    <a href="#">Profile</a>
    <a href="#">My Defails</a>
</div>
)

Ваша функция также может принимать параметры, например здесь.

2. Метод расширения HtmlHelper

Добавьте следующий код в любом месте вашего проекта:

namespace System.Web.Mvc
{
    public static class HtmlHelperExtensions
    {
        public static HtmlDefaultPanel DefaultPanel(this HtmlHelper html, string title)
        {
            html.ViewContext.Writer.Write(
            "<div class=\"panel\">" +
            "<div class=\"panel-inner\">" +
            "<p class=\"panel-title\">" + title + "</p>" +
            "<div class=\"panel-content\">"
            );

            return new HtmlDefaultPanel(html.ViewContext);
        }
    }

    public class HtmlDefaultPanel : IDisposable
    {
        private readonly ViewContext _viewContext;
        public HtmlDefaultPanel(ViewContext viewContext)
        {
            _viewContext = viewContext;
        }
        public void Dispose()
        {
            _viewContext.Writer.Write(
            "</div>" +
            "</div>" +
            "</div>"
            );
        }
    }
}

Использование:

@using (Html.DefaultPanel("title2"))
{
    <div class="panel-content-inner">
        <p>Welcome back, please select from the following options</p>
        <a href="#">Profile</a>
        <a href="#">My Defails</a>
    </div>
}

Метод расширения записывается непосредственно в контекст. Хитрость заключается в возврате одноразового объекта, метод Dispose которого будет выполнен в конце блока using.

Ответ 2

Я не знаю, могут ли методы @helper сделать это, но расширения HtmlHelper конечно могут. Вы упоминали пример Html.BeginForm(), который, вероятно, наиболее известен - все, что делает, возвращает объект, который реализует IDisposable, что означает, что при вызове метода Dispose() он просто вызывает бесплатный метод Html.EndForm() для добавьте соответствующие закрывающие теги.

Было бы очень просто сделать что-то подобное для вашего HTML-кода. Вы можете просмотреть исходный код ASP.NET MVC HtmlHelpers в http://aspnetwebstack.codeplex.com/ - код BeginForm() может быть определен как просматривается здесь.