I've got a view that iterates a collection and calls DisplayFor()
for each element in the collection.
I need to manually iterate (as opposed to passing the collection to DisplayFor) in order to tell the template if a break in the list should be drawn. The items in the list will only be of 2 types, ordered by them, so I only need to show this break once.
My template is found and called correctly.
I can see the HTML it generates correctly, ie: DisplayFor().ToHtmlString()
I can set this HTML as a scoped variable, ie: var html = DisplayFor().ToHtmlString()
..
But even Html.Raw(html)
does not render it in the browser - the HTML has simply vanished.
What's going on?
var renderBreakInList = Model.Items.Any(x => x.IsSomeType);
foreach(var item in Model.Items)
{
var renderBreak = renderBreakInList && item.IsOtherType;
Html.DisplayFor(x => item, new { renderBreak = renderBreak });
if (renderBreak)
{
renderBreakInList = false;
}
}
The Html.DisplayFor
method in itself does not render anything to the response just returns the generated HTML as a MvcHtmlString
.
In order to actually write the rendered HTML to the response you need to tell this to Razor with using the @
sign:
@Html.DisplayFor(x => item, new { renderBreak = renderBreak })
So your whole code should look like this:
@{
var renderBreakInList = Model.Items.Any(x => x.IsSomeType);
foreach(var item in Model.Items)
{
var renderBreak = renderBreakInList && item.IsOtherType;
@Html.DisplayFor(x => item, new { renderBreak = renderBreak })
if (renderBreak)
{
renderBreakInList = false;
}
}
}
Or you can use the WebPageBase.Write
method (which gets called under the hood when using the @
sign):
Write(Html.DisplayFor(x => item, new { renderBreak = renderBreak }));
finally figured this out after trying a lot of different things and reworking how I tell the Template to draw the break.
Rather than send a bool which I'd prefer to make the template more robust (if the order changes), I'm passing in the ID of the item that should draw the break.
@{
var breakItem = Model.Items.FirstOrDefault(x => renderBreakInList && x.IsSomeType);
var breakID = breakItem == null ? (long?)null : (long)breakItem.ID;
}
@Html.DisplayFor(x => x.Items, new { breakID = breakID })
Also like nemesv pointed out, Html.DisplayFor()
needs to be prepended with @
. I got out of the habit of doing this inside code blocks because I would always get the 'once inside a code block you don't need @` error..