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.

6
demandé sur tereško 2011-02-05 00:47:34

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.

3
répondu John Boker 2011-02-08 13:31:24

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")
}
2
répondu Patrick Herrington 2012-10-02 02:32:26

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 :)

0
répondu RobertjanTuit 2014-09-21 21:41:41

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>
0
répondu daveaglick 2014-12-18 22:02:20

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>
    }
}
-1
répondu ajma 2011-02-04 22:43:07