MVC 3 Razor, помощники с пользовательской разметкой / разделом
Я даже не уверен, возможно ли это, но я решил проверить, есть ли способ сделать это проще.
Во-первых, у меня есть несколько разметок на моем сайте, которые выглядят так:
<div class="module">
<h3>Title</h3>
<div>
<p>Information goes here</p>
</div>
</div>
То, что я хочу сделать, это обернуть это в какой-то вспомогательный / раздел, чтобы я мог сделать что-то вроде этого
@MyHelper("This is my Title") {
<p>Here is my custom markup</p>
}
Затем, когда он рендерится, он вставит заголовок, переданный через параметр между <h3></h3>
и пользовательская разметка в div. Пользовательская разметка может быть любой: от теста, до элементов управления, до частичного представления. Это то, что возможно?
4 ответа
Что ж, вот "стандартный" способ сделать что-то близкое к нему, используя вспомогательное расширение HTML. Очень простая версия того, что Html.BeginForm()
делает.
Подход: просто верните IDisposable, и пусть using
Заявление позаботится об остальном.
Это всего лишь пример концепции (хотя она работает). Не предназначен для немедленного повторного использования. Написан быстро с большим количеством ярлыков, а не с рабочим кодом, множеством возможностей для улучшения и оптимизации, может иметь глупые ошибки, может использовать TagBuilder и т. Д. И т. Д. Может быть легко изменен для повторного использования класса Wrapper для различных... оберток (может даже быть универсальным уже в ASP.NET MVC - не было необходимости в этом).
public static class WrapHelper
{
private class Wrapper : IDisposable
{
private bool disposed;
private readonly TextWriter writer;
public Wrapper(HtmlHelper html)
{
this.writer = html.ViewContext.Writer;
}
public void Dispose()
{
if (disposed) return;
disposed = true;
writer.WriteLine(" </div>");
writer.WriteLine("</div>");
}
}
public static IDisposable Wrap(this HtmlHelper html, string title)
{
TextWriter writer = html.ViewContext.Writer;
writer.WriteLine("<div class=\"module\">");
writer.WriteLine(" <h3>" + html.Encode(title) + "</h3>");
writer.WriteLine(" <div>");
return new Wrapper(html);
}
}
Использование:
@using (Html.Wrap("Title"))
{
<p>My very own markup.</p>
}
Есть и другой способ, без одноразового трюка, который также требует немного меньше работы, отлично подходит для маленьких помощников.
@helper MyHelper(string title, Func<object, object> markup) {
<div class="module">
<h3>Title</h3>
<div>
<p>@markup.DynamicInvoke(this.ViewContext)</p>
</div>
</div>
}
Использование этого помощника выглядит так:
@MyHelper("This is my Title",
@<p>Here is my custom markup</p>
)
Или с несколькими строками:
@MyHelper("This is my Title",
@<text>
<p>More than one line</p>
<p>Of markup</p>
</text>
)
Элементы управления Telerik MVC использовали этот трюк, например, чтобы вы могли добавить свой код JavaScript при загрузке документа.
Вот также хороший пример. Здесь также есть некоторая информация.
@TheKaneda, спасибо за понимание. Я взял вашу идею и расширил ее так, чтобы вы указали имя PartialView, и оно знает, как его проанализировать.
<Extension()> _
Public Function UseTemplate(ByVal html As HtmlHelper, ByVal PartialView As String) As IDisposable
Return New TemplateWrapper(html, PartialView)
End Function
Public Class TemplateWrapper
Implements IDisposable
Private _HtmlHelper As HtmlHelper
'Index 0 is header
'Index 1 is footer
Private _TemplateWrapper As String()
Public Sub New(ByVal Html As HtmlHelper, ByVal PartialView As String)
_TemplateWrapper = Html.Partial(PartialView).ToHtmlString.Split("@@RenderBody()")
_HtmlHelper = Html
_HtmlHelper.ViewContext.Writer.Write(_TemplateWrapper(0))
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
_HtmlHelper.ViewContext.Writer.Write(_TemplateWrapper(1).Substring(12))
End Sub
End Class
Используйте то же использование, что и в примере @ TheKaneda. В вашем частичном представлении вместо вызова @RenderBody () просто поместите @@RenderBody(), который действует как флаг для средней части вашего контента. Извините за перевод VB.
Использует пример моего использования.
Using Html.UseTemplate("ContentWrapper")
@Html.EditorFor(Function(m) m.Var1, "TemplateHint")
@Html.EditorFor(Function(m) m.Var2, "TemplateHint")
@Html.EditorFor(Function(m) m.Var3)
End Using
Мой Частичный выглядит так...
<div class="content">
@@RenderBody()
</div>
Если вы используете Razor и MVC 3, очень легко написать быстрый вспомогательный метод, который будет находиться в папке app_code (я назову его MyHtmlHelpers)
Я бы попробовал что-то немного другое и немного проще, например:
@helper myTemplate(string title, string markup){
<div class="module">
<h3>@title</h3>
@markup
</div>
}
И способ, которым вы используете его из файла.cshtml, выглядит следующим образом:
@MyHtmlHelpers.myTemplate('title','markup')
Должно работать, если я вас правильно понимаю.