Razor Func<объект, объект>, смешанный с MvcHtmlString

Я не гуру в синтаксисе Razor, но пытаюсь создать универсальную библиотеку, используя беглые элементы интерфейса Telerik.

У меня есть следующие части (примерно):

public static MyBox Box(this HtmlHelper helper)
{
    return new MyBox(helper.ViewContext);
}

а также:

/// <summary>
/// http://geekswithblogs.net/shaunxu/archive/2010/04/10/lt-gt-htmlencode-ihtmlstring-and-mvchtmlstring.aspx
/// </summary>
public class MyBox : IHtmlString
{
    private readonly ViewContext _viewContext;
    private string _content;
    private string _title;

    public MyBox(ViewContext viewViewContext)
    {
        _viewContext = viewViewContext;
    }

    /// <summary>
    /// See: http://haacked.com/archive/2011/02/27/templated-razor-delegates.aspx
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public MyBox Content(Func<object, object> value)
    {
        _content = value.DynamicInvoke(_viewContext).ToString();
        return this;
    }

    /// <summary>
    /// See: http://haacked.com/archive/2011/02/27/templated-razor-delegates.aspx
    /// </summary>
    /// <param name="values"></param>
    /// <returns></returns>
    public MyBox Content(params Func<object, object>[] values)
    {
        foreach (var value in values)
        {
            _content += value.DynamicInvoke(_viewContext).ToString();
        }
        return this;
    }

    public MyBox Content(MvcHtmlString content)
    {
        _content = content.ToString();
        return this;
    }

    public MyBox Title(string title)
    {
        _title = title;
        return this;
    }

    public string ToHtmlString()
    {
        using (var stringWriter = new StringWriter())
        {
            WriteHtml((TextWriter)stringWriter);
            return stringWriter.ToString();
        }
    }

    public void Render()
    {
        using (var writer = new HtmlTextWriter(_viewContext.Writer))
            WriteHtml(writer);
    }

    protected virtual void WriteHtml(TextWriter writer)
    {
        writer.WriteLine("<!-- START BOX -->");
        writer.WriteLine("<h1>" + _title + "</h1>));
        writer.WriteLine(_content);
        writer.WriteLine("<!-- END BOX -->");
    }
}

У меня также есть набор методов расширения Html, которые возвращают MvcHtmlString. Один пример (упрощенный):

public static class GuiElementExtensions
    {
        private const string FieldContainerHeadingTemplate = @"
<tr><th style=""text-align:left"" colspan=""2"">{0}</th></tr>
";

    public static MvcHtmlString GuiFieldContainerHeading(this HtmlHelper helper, string text)
        {
            return new MvcHtmlString(String.Format(FieldContainerHeadingTemplate, text));
        }
}

Затем в моем файле.cshtml я делаю следующее:

  @using (Html.BeginForm())
       {
           @(Html.Gui()
                      .Box()
                      .Title("Hello World!")
                      .Content(
                                @<h1>Hello World! This is the cool Gui.Box</h1> 
                       )
        )
 }

Какие звонки public MyBox Content(Func<object, object> value)и работает. Точно так же, когда я пытаюсь сделать следующее:

  @using (Html.BeginForm())
       {
           @(Html.Gui()
                      .Box()
                      .Title("Hello World!")
                      .Content(
                                Html.GuiFieldContainerHeading("SubHeading 1")
                       )
        )
 }

Радостно зовет public MyBox Content(MvcHtmlString content) и работает как положено.

Но, однако, когда я пытаюсь сделать следующее, я не могу понять, как работает механизм компилятора Razor. Как я могу получить его, чтобы вернуть сумму

  • @<h1>Hello World! This is Gui().Box()</h1> (который является Func)
  • Html.GuiFieldContainerHeading("SubHeading 1") (который является MvcHtmlString)

как один объект (будь то Func, MvcHtmlString, что угодно, или список объектов? Я хотел бы написать общий синтаксис Razor внутри списка параметров для функции Content в моем классе MyBox, например так:

  @using (Html.BeginForm())
       {
           @(Html.Gui()
                      .Box()
                      .Title("Hello World!")
                      .Content(
                                @<h1>Hello World! This is Gui().Box()</h1> 
                                Html.GuiFieldContainerHeading("SubHeading 1")
                Html.TextBoxFor(model => model.Name)
                @<h2>Hello there!</h2>
                       )
        )
 }

Я на правильном пути, или есть гораздо более простой способ делать то, что я хочу? Я хочу собрать все "общие элементы графического интерфейса" в нашей системе в общую библиотеку DLL, поэтому не каждому разработчику в моей организации необходимо заново изобретать колесо для каждого проекта.

Любая помощь приветствуется.


ОК, следующая проблема:

Я обобщил Box в контейнер и создал два подкласса: Box и HighlightArea. Тем не менее, используя следующий код, Razor пинает меня с сообщением

Встроенные блоки разметки (@

Content) не могут быть вложенными. Разрешается только один уровень встроенной разметки.

Код не работает, это:

 @(Html.Gui()
              .Box()
              .Title("BoxTitle")
              .Content(@<text>
                        <h1>Hello World! This is the box content</h1> 
                        @Html.GuiFieldContainerHeading("This is the heading")
                        @(Html.Gui().HighlightArea()
                              .Content(
                                @Html.ValidationSummary()
                                @<h1>Jalla</h1>
                              )
                        )
                       </text>
               )

У нас есть обходной путь для этого? Или мой подход неосуществим?

1 ответ

Решение

Вы могли бы использовать <text> тег, чтобы объединить все в один параметр.

@using (Html.BeginForm())
{
    @(Html.Gui()
        .Box()
        .Title("Hello World!")
        .Content(
            @<text>
                <h1>Hello World! This is Gui.Box</h1> 
                @Html.GuiFieldContainerHeading("SubHeading 1")
                @Html.TextBoxFor(model => model.Name)
                <h2>Hello there!</h2>
            </text>
        )
    )
}

Я думаю, твой пример на самом деле не работает. Если я не ошибаюсь, вы можете заставить его работать так:

@<h1>Hello World! This is Gui.Box</h1>
 + Html.GuiFieldContainerHeading("SubHeading 1")
 + Html.TextBoxFor(model => model.Name)
 + @<h2>Hello there!</h2>

Но <text> тег кажется проще.

Другие вопросы по тегам