If you have an IHtmlContentBuilder in your Razor view, you can use these extensions.
public static IHtmlContentBuilder AppendRazor(this IHtmlContentBuilder htmlContentBuilder, Func<IHtmlContent, dynamic> lamda)
{
var html = lamda(null);
return htmlContentBuilder.AppendHtml(html);
}
public static IHtmlContentBuilder AppendRazor<T>(this IHtmlContentBuilder htmlContentBuilder, Func<T, IHtmlContent> lamda, T model)
{
var html = lamda(model);
return htmlContentBuilder.AppendHtml(html);
}
Usage
@{
HtmlContentBuilder contentBuilder = new HtmlContentBuilder();
contentBuilder.AppendRazor(@<text><p>Hello @Model.Name<p></text>);
contentBuilder.AppendRazor(@<text><p>Hello @item.CustomerName<p></text>, customer);
}
<div>
@contentBuilder
</div>
Just in case anyone else finds this post (as I did), Andy's Update is almost there. In addition to the example given, all you have to do to access the 'int' in the example given is reference @item
. In @<text></text>
blocks, the variable item
contains the model it was called on.
Here's an example of how it can be used:
@model PageData
@{
Func<Customer, object> sayHi =
@<text>
<li>Hello @(item.FirstName)!</li>
</text>;
}
<ul>
@foreach(var customer in Model.Customers)
{
sayHi(customer);
}
</ul>
In most instances you should probably use a partial view instead of a function like this. But in the rare instances that a partial view is not possible (such as when using the RazorEngine library), this works.
Basically the OP already answered the problem in that you could do something like:
@{
Func<dynamic, object> a = @<text>
Some Text
</text>;
@a(new object())
}
If the text is for a single line only you could even use the "@:" operator, just remmebr to have a semicolon (or if it needs any closing brackets or parenthesis) on the next line, as in the following example:
@{
Func<dynamic, object> a = @: Some Text
;
@a(new object())
}
However you can capture it directly as a string if you want
@{
string a = ((Func<dynamic, object>)(@<text>
Some Text
</text>))("").ToString();
@a //Output directly as a string
}
You could even encapsulate it in a function:
@functions{
public string ToString(Func<dynamic, object> input)
{
return input("").ToString();
}
}
@{
string a = ToString(@<text>
Some Text
</text>);
@a //Output directly as a string
}
Perhaps you can use HtmlString? I don't think I like this much, but here's what I'd try as an exact translation of what you have...
@{
var t = new HtmlString("<a class='tab' href=''>Tab name</a>");
var tc = new HtmlString("<div class='tabcontent'><p>Here goes tab content</p></div>");
}
@tabs(t, tc)
So... I don't know what your Spark macro looks like, but it seems like an opportunity to use a helper in Razor. You might have something like:
@helper Tabs(string tabName, string tabContent)
{
<!-- some wrapper code -->
<a class="tab" href="">@(tabName)</a>
<!-- some more wrapper code -->
<div class="tabcontent">
<p>@(tabContent)</p>
</div>
<!-- still more wrapper code -->
}
Then you call that from in your page like so:
@Tabs("Tab Name", "Here goes tab content")