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 p>) не могут быть вложенными. Разрешается только один уровень встроенной разметки.
Код не работает, это:
@(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>
тег кажется проще.