2011-02-04 13 views
6

Tengo un Page.cshtml similar al siguiente (que no funciona):¿Hay alguna manera de hacer que @section sea opcional con asp.net mvc Razor ViewEngine?

@{ 
    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> 
    } 
} 

Como ya he dicho, esto no funciona. No quiero definir la sección si no hay nada en la colección. ¿Hay alguna manera de hacer que algo como esto funcione? Si no, ¿cuáles son mis otras opciones? Soy muy nuevo en este Razor ViewEngine.

Editar

En mi diseño que tengo:

@if(IsSectionDefined("ContentRight")) 
{ 
    <div class="right"> 
     RenderSection("ContentRight") 
    </div> 
} 

lo que no queremos es que el div a la salida cuando la sección está vacía.

Respuesta

3

que terminé haciendo algo un poco hacky para que funcione como lo necesitaba.

en mi página tengo:

@{ 
    Layout = "../Shared/Layouts/_Layout.cshtml"; 
    var mycollection = (ViewBag.TheCollection as IQueryable<MyCollectionType>); 
    ViewBag.ShowContentRight = mycollection != null && mycollection.Count() > 0; 
} 

entonces en mi diseño que tengo:

@if(IsSectionDefined("ContentRight") && (ViewBag.ShowContentRight == null ||ViewBag.ShowContentRight == true)) 
{ 
    <div class="right"> 
     RenderSection("ContentRight") 
    </div> 
} 
else if(IsSectionDefined("ContentRight")) 
{ 
    RenderSection("ContentRight") 
} 

Si se define la sección tiene que ser prestado, pero si no hay contenido no quiero el <div> s

Si hay una manera mejor que me gustaría saber.

+0

Desafortunadamente esa es probablemente su mejor opción ahora mismo. Otra posible opción es tratar de llamar directamente a DefineSection, que es a lo que se traduce "@section". El problema es que no puedes poner Markup dentro de una lambda en Razor v2 (algo que estamos viendo para el futuro), así que vas a tener que definir tu contenido en un constructo @helper y llamar a ese helper desde la lambda de DefineSection . Al final, puede que te resulte más fácil hacerlo de la forma en que lo haces. ¡Pero veremos cómo mejorar esto en futuras versiones! –

-1

Usted puede envolver su sección entera en una sentencia if con IsSectionDefined

Layout.cshtml:

@if (IsSectionDefined("ContentRight")) 
{ 
    <div> 
    @RenderSection(name: "ContentRight", required: false) 
    </div> 
} 

Su página 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> 
    } 
} 
+0

que desea poner el IsSectionDefined en el archivo de diseño y llame rendersection con requerida = false – ajma

+0

que es lo que tengo actualmente, pero es sacando el div porque la sección está definida incluso si no hay nada en él. –

+0

¿Qué sucede si los divs que lo rodean están envueltos con IsSectionDefined? – ajma

2

El procesador está esperando que el método sea llamado alguna vez en el archivo de diseño. Puede falsificar el renderizador y usar condicionales "globales" (pensar en iniciar sesión).

@{ 
    ViewBag.content = RenderBody(); 
} 
@if (Request.IsAuthenticated) { 
     @ViewBag.content; 
} 
else { 
     @Html.Partial("_LoginPartial") 
} 
0

método de extensión con la información de campo de sólo lectura estática privada para Potencia:

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); 
     } 
    } 
} 

En su cshtml:

@{ this.EnsureSectionsAreRegisteredAsRendered("SectionName1", " SectionName2", "…"); } 

Sí, sí, sí .... lo sé ... ¡Mal reflejo! Utilice a su propio riesgo :)

0

utilizo el siguiente método en mi clase de vista base (de este excelente 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 usted no tiene una clase vista base, recomiendo uno porque le permite agregar todo tipo de funcionalidades extra a sus puntos de vista.Basta con crear una clase con la siguiente firma: public abstract class MyViewPage<T> : WebViewPage<T> y luego ponerlo en su web.config:

<system.web.webPages.razor> 
    <pages pageBaseType="MyViewPage"> 
    ... 
    </pages> 
</system.web.webPages.razor> 
Cuestiones relacionadas