2014-05-07 16 views
27

Tôi có một hàm trợ giúp Razor để tạo ra một bảng HTML có thể tái sử dụng giúp tôi ghi lại HTML giống nhau nhiều lần.Tạo các thành phần xem HTML có thể tái sử dụng bằng Razor trong ASP.NET MVC

@helper DefaultPanel(string panelTitle) { 
    <div class="panel"> 
     <div class="panel-logo"><img src="/logo.png"></div> 
      <div class=panel-inner"> 
       <p class="panel-title">@panelTitle</p> 
       <div class="panel-content"> 
        /* Can I pass content to be rendered in here here? */ 
       </div> 
      </div> 
     </div> 
    </div> 
} 

Tôi đang tự hỏi, là nó có thể tái sử dụng helper này để điền .panel-content với HTML hơn để cho phép linh hoạt hơn nữa và tái sử dụng mã - tương tự một cái gì đó như dưới đây:

@LayoutHelpers.DefaultPanel("Welcome back") { 
    <div class="panel-content-inner"> 
     <p>Welcome back, please select from the following options</p> 
     <a href="#">Profile</a> 
     <a href="#">My Defails</a> 
    </div> 
} 

Trong khi sử dụng .NET MVC, tôi nhận thấy rằng Html.BeginForm() thực hiện điều tương tự khi bao bọc mã trong tuyên bố @using trong tuyên bố Html.BeginForm, như vậy:

@using (Html.BeginForm("Index", "Login", FormMethod.Post)) 
{ 
    <div>This content gets rendered within the <form></form> markup.</div> 
} 

Nhưng điều này có thể thực hiện bằng phương pháp @helper không? Nếu không, có thể tạo phần mở rộng HtmlHelper để thực hiện tương tự như cách phương thức Html.BeginForm() không?

Bạn có thể làm một điều rất giống nhau bằng cách sử dụng cú pháp @section như đã thấy here

enter image description here

Điều này có vẻ giống như một cái gì đó sẽ thực sự hữu ích để có thể làm, và kỳ lạ mà không có cách nào dễ dàng để làm điều đó ở cấp độ thành phần.

Trả lời

34

Có hai cách để đạt được chức năng được yêu cầu.

1. @helper

Tạo @helper mà chấp nhận bất cứ điều gì các thông số bạn cần cộng thêm một chức năng (tham số đối tượng duy nhất, lợi nhuận đối tượng):

@helper DefaultPanel(string panelTitle, Func<object, object> content) 
{ 
    <div class="panel"> 
     <div class="panel-logo"> 
       <img src="/logo.png" /> 
      </div> 
      <div class="panel-inner"> 
       <p class="panel-title">@panelTitle</p> 
       <div class="panel-content"> 
        @content(null) 
       </div> 
      </div> 
    </div> 
} 

Cách sử dụng:

@DefaultPanel("title", 
@<div class="panel-content-inner"> 
    <p>Welcome back, please select from the following options</p> 
    <a href="#">Profile</a> 
    <a href="#">My Defails</a> 
</div> 
) 

Chức năng của bạn cũng có thể chấp nhận các tham số, ví dụ here.

2.phương pháp mở rộng HtmlHelper

Thêm mã sau đây bất cứ nơi nào trong dự án của bạn:

namespace System.Web.Mvc 
{ 
    public static class HtmlHelperExtensions 
    { 
     public static HtmlDefaultPanel DefaultPanel(this HtmlHelper html, string title) 
     { 
      html.ViewContext.Writer.Write(
      "<div class=\"panel\">" + 
      "<div class=\"panel-inner\">" + 
      "<p class=\"panel-title\">" + title + "</p>" + 
      "<div class=\"panel-content\">" 
      ); 

      return new HtmlDefaultPanel(html.ViewContext); 
     } 
    } 

    public class HtmlDefaultPanel : IDisposable 
    { 
     private readonly ViewContext _viewContext; 
     public HtmlDefaultPanel(ViewContext viewContext) 
     { 
      _viewContext = viewContext; 
     } 
     public void Dispose() 
     { 
      _viewContext.Writer.Write(
      "</div>" + 
      "</div>" + 
      "</div>" 
      ); 
     } 
    } 
} 

Cách sử dụng:

@using (Html.DefaultPanel("title2")) 
{ 
    <div class="panel-content-inner"> 
     <p>Welcome back, please select from the following options</p> 
     <a href="#">Profile</a> 
     <a href="#">My Defails</a> 
    </div> 
} 

Phương pháp mở rộng ghi trực tiếp vào ngữ cảnh. Bí quyết là trả lại một đối tượng dùng một lần, phương thức Vứt bỏ sẽ được thực hiện ở cuối khối using.

+0

Tôi bỏ phiếu cho lựa chọn 2. – MikeSW

+0

Hoàn hảo, thứ hai hoạt động như một sự quyến rũ! Cảm ơn bạn đã dành thời gian để viết một câu trả lời kỹ lưỡng như vậy quá. –

+0

câu trả lời hay. Tôi thích thứ hai. – pixparker

1

Tôi không biết liệu các phương pháp @helper có thể thực hiện điều này hay không nhưng chắc chắn có thể thực hiện được HtmlHelper tiện ích mở rộng. Bạn đã đề cập đến ví dụ Html.BeginForm() có lẽ là nổi tiếng nhất - tất cả những gì thực hiện là trả về một đối tượng thực hiện IDisposable có nghĩa là khi phương thức Dispose() được gọi là phương thức Html.EndForm() miễn phí để thêm các thẻ đóng thích hợp.

Sẽ rất đơn giản để thực hiện điều gì đó tương tự cho mã HTML của bạn. Bạn có thể xem mã nguồn tới ASP.NET MVC HtmlHelpers tại http://aspnetwebstack.codeplex.com/ - mã BeginForm() có thể được cụ thể là viewed here.

Các vấn đề liên quan