Y a-t-il un moyen de rendre un @section optionnel avec le asp.net mvc Razor ViewEngine?
j'ai une Page.CSHTML similaire à ce qui suit (qui ne fonctionne pas):
@{
Layout = "../Shared/Layouts/_Layout.cshtml";
var mycollection = (ViewBag.TheCollection as IQueryable<MyCollectionType>);
}
<h2>@ViewBag.Title</h2>
content here
@if (mycollection != null && mycollection.Count() > 0)
{
@section ContentRight
{
<h2>
Stuff
</h2>
<ul class="stuff">
@foreach (MyCollectionType item in mycollection )
{
<li class="stuff-item">@item.Name</li>
}
</ul>
}
}
Comme je l'ai dit, cela ne fonctionne pas. Je ne veux pas définir la section s'il n'y a rien dans la collection. Est-il possible d'avoir quelque chose comme ce travail? Si non, quelles sont mes options? Je suis très nouveau à ce viseur de rasoir.
Modifier
dans ma disposition j'ai:
@if(IsSectionDefined("ContentRight"))
{
<div class="right">
RenderSection("ContentRight")
</div>
}
ce que je ne veux pas, c'est que le div sorte quand la section est vide.
5 réponses
j'ai fini par faire quelque chose d'un peu hacky pour qu'il fonctionne comment j'en avais besoin.
sur ma page j'ai:
@{
Layout = "../Shared/Layouts/_Layout.cshtml";
var mycollection = (ViewBag.TheCollection as IQueryable<MyCollectionType>);
ViewBag.ShowContentRight = mycollection != null && mycollection.Count() > 0;
}
puis dans ma disposition j'ai:
@if(IsSectionDefined("ContentRight") && (ViewBag.ShowContentRight == null ||ViewBag.ShowContentRight == true))
{
<div class="right">
RenderSection("ContentRight")
</div>
}
else if(IsSectionDefined("ContentRight"))
{
RenderSection("ContentRight")
}
si la section est définie elle doit être rendue, mais s'il n'y a pas de contenu Je ne veux pas le <div>
s
S'il y a une meilleure façon de le savoir.
le renderer s'attend à ce que la méthode soit appelée dans le fichier layout. Vous pouvez mystifier le renderer et utiliser des conditionnels "global" (pensez login).
@{
ViewBag.content = RenderBody();
}
@if (Request.IsAuthenticated) {
@ViewBag.content;
}
else {
@Html.Partial("_LoginPartial")
}
méthode d'Extension avec private static readonly domaine info pour les perf:
private static readonly FieldInfo RenderedSectionsFieldInfo = typeof(WebPageBase).GetField("_renderedSections", BindingFlags.Instance | BindingFlags.NonPublic);
public static void EnsureSectionsAreRegisteredAsRendered(this WebPageBase webPageBase, params string[] sectionNames)
{
var renderedSections = RenderedSectionsFieldInfo.GetValue(webPageBase) as HashSet<string>;
if (renderedSections == null)
{
throw new WebCoreException("Could not get hashset from private field _renderedSections from WebPageBase");
}
foreach (var sectionName in sectionNames)
{
if (!renderedSections.Contains(sectionName))
{
renderedSections.Add(sectionName);
}
}
}
dans votre cshtml:
@{ this.EnsureSectionsAreRegisteredAsRendered("SectionName1", " SectionName2", "…"); }
Oui, oui, oui.... Je sais.... mauvaise réflexion! Utilisez à vos risques et périls :)
j'utilise la méthode suivante dans ma classe de base de vue (à partir de cet excellent billet de blog http://haacked.com/archive/2011/03/05/defining-default-content-for-a-razor-layout-section.aspx / ):
public HelperResult RenderSection(string name, Func<dynamic, HelperResult> defaultContents)
{
if (IsSectionDefined(name))
{
return RenderSection(name);
}
return defaultContents(null);
}
si vous n'avez pas de classe de base de vue, je vous en recommande une parce qu'elle vous permet d'ajouter toutes sortes de petites fonctionnalités supplémentaires à vos vues. Il suffit de créer une classe avec la signature suivante: public abstract class MyViewPage<T> : WebViewPage<T>
et de la mettre dans votre web.config
:
<system.web.webPages.razor>
<pages pageBaseType="MyViewPage">
...
</pages>
</system.web.webPages.razor>
vous pouvez envelopper toute votre section dans une instruction if avec IsSectionDefined
Mise en page.cshtml:
@if (IsSectionDefined("ContentRight"))
{
<div>
@RenderSection(name: "ContentRight", required: false)
</div>
}
votre page cshtml:
@section ContentRight
{
@if (mycollection != null && mycollection.Count() > 0)
{
<h2>
Stuff
</h2>
<ul class="stuff">
@foreach (MyCollectionType item in mycollection )
{
<li class="stuff-item">@item.Name</li>
}
</ul>
}
}