2011-02-04 20 views
6

Tôi có một Page.cshtml tương tự như sau (không hoạt động):Có cách nào để tạo tùy chọn @section với asp.net mvc Razor ViewEngine không?

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

Như tôi đã nói, điều này không làm việc. Tôi không muốn xác định phần nếu không có gì trong bộ sưu tập. Có cách nào để có một cái gì đó như công việc này? Nếu không, các lựa chọn khác của tôi là gì? Tôi rất mới với Razor ViewEngine này.

Sửa

Trong cách bố trí của tôi, tôi có:

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

những gì tôi không muốn là div để đầu ra khi phần trống.

Trả lời

3

tôi đã kết thúc làm điều gì đó một chút hacky để làm cho nó hoạt động như thế nào tôi cần nó.

trên trang của mình tôi có:

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

sau đó trong cách bố trí của tôi, tôi có:

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

Nếu phần được định nghĩa nó phải được trả lại, nhưng nếu không có nội dung tôi không muốn số <div> s

Nếu có cách nào tốt hơn tôi muốn biết.

+0

Thật không may đó có lẽ là lựa chọn tốt nhất của bạn ngay bây giờ. Một lựa chọn khác có thể là thử và gọi trực tiếp DefineSection, đó là những gì "@section" được dịch xuống. Vấn đề là bạn không thể đặt Markup bên trong một lambda trong Razor v2 (một cái gì đó chúng tôi đang tìm kiếm trong tương lai) vì vậy bạn sẽ phải xác định nội dung của bạn trong một cấu trúc @helper và gọi helper đó từ DefineSection lambda . Cuối cùng, nó có thể kết thúc dễ dàng hơn để làm điều đó theo cách bạn có. Nhưng chúng tôi sẽ xem xét cải thiện điều này trong các phiên bản tương lai! –

-1

Bạn có thể bọc toàn phần của bạn trong một câu lệnh if với IsSectionDefined

Layout.cshtml:

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

trang cshtml của bạn:

@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

bạn muốn đặt IsSectionDefined trong file Layout và gọi rendersection với yêu cầu = false – ajma

+0

đó là những gì tôi đang có, nhưng nó xuất div bởi vì phần được xác định ngay cả khi không có gì trong đó. –

+0

nếu các div xung quanh nó được bao bọc với IsSectionDefined thì sao? – ajma

2

Trình kết xuất đang chờ phương thức được gọi đôi khi trong tệp bố cục. Bạn có thể giả mạo trình kết xuất đồ họa và sử dụng các điều kiện "toàn cầu" (nghĩ đăng nhập).

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

phương pháp mở rộng với tĩnh thông tin lĩnh vực readonly tin cho 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); 
     } 
    } 
} 

Trong cshtml của bạn:

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

Vâng, vâng, vâng .... Tôi biết ... phản ánh xấu! Sử dụng có nguy cơ của riêng bạn :)

0

tôi sử dụng phương pháp sau đây trong lớp xem cơ sở của tôi (từ bài viết trên blog tuyệt vời này 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); 
} 

Nếu bạn không có một lớp xem cơ sở, tôi khuyên bạn nên một vì nó cho phép bạn thêm tất cả các loại chức năng bổ sung nhỏ vào chế độ xem của bạn.Chỉ cần tạo một lớp học với các chữ ký sau: public abstract class MyViewPage<T> : WebViewPage<T> và sau đó đặt nó trong bạn web.config:

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