2012-01-31 28 views
10

Tôi thậm chí không chắc chắn nếu điều này là có thể, nhưng tôi nghĩ tôi sẽ kiểm tra xem có cách nào để thực hiện điều này dễ dàng hơn không.MVC 3 Dao cạo, Người trợ giúp với đánh dấu tùy chỉnh/phần

Trước tiên, tôi có một số đánh dấu lặp lại trong trang web của tôi trông như thế này:

<div class="module"> 
    <h3>Title</h3> 
    <div> 
     <p>Information goes here</p> 
    </div> 
</div> 

Những gì tôi muốn làm là quấn này trong một số loại helper/phần vì vậy mà tôi có thể làm một cái gì đó như thế này

@MyHelper("This is my Title") { 
    <p>Here is my custom markup</p> 
} 

Sau đó, khi nó hiển thị, nó sẽ truyền tiêu đề được chuyển qua thông số giữa <h3></h3> và đánh dấu tùy chỉnh trong divs. Đánh dấu tùy chỉnh có thể là bất kỳ điều gì từ kiểm tra, để điều khiển biểu mẫu, đến một chế độ xem một phần. Đây có phải là cái gì đó có thể?

Trả lời

12

Vâng, đây là cách "chuẩn" để làm điều gì đó gần với nó, sử dụng phần mở rộng trợ giúp HTML. Một phiên bản rất đơn giản của những gì Html.BeginForm() làm.

Cách tiếp cận: Chỉ cần trả lại IDisposable và để câu lệnh using xử lý phần còn lại.

Đây chỉ là một ví dụ về khái niệm (mặc dù nó hoạt động). Không có ý định tái sử dụng ngay lập tức. Viết nhanh với nhiều phím tắt, không phải mã sản xuất, nhiều cơ hội để cải thiện và tối ưu hóa, có thể có những sai lầm ngớ ngẩn, có thể sử dụng TagBuilder, v.v. Có thể dễ dàng sửa đổi để sử dụng lại lớp Wrapper cho các gói ... khác nhau (thậm chí có thể là một trong những generic đã có trong ASP.NET MVC - đã không có một nhu cầu cho một).

public static class WrapHelper 
{ 
    private class Wrapper : IDisposable 
    { 
     private bool disposed; 
     private readonly TextWriter writer; 

     public Wrapper(HtmlHelper html) 
     { 
      this.writer = html.ViewContext.Writer; 
     } 

     public void Dispose() 
     { 
      if (disposed) return; 

      disposed = true; 

      writer.WriteLine(" </div>"); 
      writer.WriteLine("</div>"); 
     } 
    } 

    public static IDisposable Wrap(this HtmlHelper html, string title) 
    { 
     TextWriter writer = html.ViewContext.Writer; 

     writer.WriteLine("<div class=\"module\">"); 
     writer.WriteLine(" <h3>" + html.Encode(title) + "</h3>"); 
     writer.WriteLine(" <div>"); 

     return new Wrapper(html); 
    } 
} 

Cách sử dụng:

@using (Html.Wrap("Title")) 
{ 
    <p>My very own markup.</p> 
} 
+0

Đây chính xác là những gì tôi đang tìm kiếm. – Josh

+0

Có một ví dụ đơn giản hơn tại http://stackoverflow.com/questions/7196276/creating-mvc3-razor-helper-like-helper-beginform –

+0

Tôi gặp khó khăn khi thấy điều gì làm cho nó đơn giản hơn, xem xét giải pháp là chính xác cùng ... Mã bổ sung duy nhất trong ví dụ này là để đáp ứng các yêu cầu trong câu hỏi - và kiểm tra sơ bộ để tránh các tác dụng phụ của Dispose được gọi hai lần. – JimmiTh

0

Nếu bạn đang sử dụng Razor và MVC 3 nó thực sự dễ dàng để viết một phương pháp helper nhanh chóng mà sẽ đi bên trong thư mục App_Code, (Tôi sẽ đặt tên cho nó MyHtmlHelpers)

tôi muốn thử một cái gì đó hơi khác một chút và một chút dễ dàng hơn như:

@helper myTemplate(string title, string markup){ 
    <div class="module"> 
     <h3>@title</h3> 
     @markup 
    </div> 
} 

và cách bạn u se nó từ một tập tin .cshtml như sau:

@MyHtmlHelpers.myTemplate('title','markup') 

Nó sẽ hoạt động, nếu tôi hiểu bạn một cách chính xác.

+1

Tôi không muốn đánh dấu là tham số chuỗi, vì tôi muốn có đánh dấu là html thông thường trong chế độ xem của mình. Những gì tôi đang tìm kiếm để làm là bắt chước với một người trợ giúp trong MVC 3 như thế nào trong MVC 2 bạn có thể có '<% sử dụng (Html.Beginform()) {%> html đánh dấu <% } %>' – Josh

3

@TheKaneda, Cảm ơn sự thấu hiểu. Tôi lấy ý tưởng của bạn và mở rộng nó, sao cho bạn cung cấp một tên PartialView và nó biết cách phân tích nó.

<Extension()> _ 
Public Function UseTemplate(ByVal html As HtmlHelper, ByVal PartialView As String) As IDisposable 
    Return New TemplateWrapper(html, PartialView) 
End Function 

Public Class TemplateWrapper 
    Implements IDisposable 

    Private _HtmlHelper As HtmlHelper 

    'Index 0 is header 
    'Index 1 is footer 
    Private _TemplateWrapper As String() 

    Public Sub New(ByVal Html As HtmlHelper, ByVal PartialView As String) 

     _TemplateWrapper = Html.Partial(PartialView).ToHtmlString.Split("@@RenderBody()") 

     _HtmlHelper = Html 
     _HtmlHelper.ViewContext.Writer.Write(_TemplateWrapper(0)) 

    End Sub 

    Public Sub Dispose() Implements IDisposable.Dispose 

     _HtmlHelper.ViewContext.Writer.Write(_TemplateWrapper(1).Substring(12)) 

    End Sub 

End Class 

Sử dụng cùng cách sử dụng như ví dụ của @ TheKaneda. Trong chế độ xem một phần của bạn, thay vì gọi @RenderBody(), chỉ cần đặt @@ RenderBody() hoạt động như một lá cờ cho phần giữa của nội dung của bạn. Xin lỗi vì bản dịch VB.

Sử dụng ví dụ về cách sử dụng của tôi.

Using Html.UseTemplate("ContentWrapper") 

    @Html.EditorFor(Function(m) m.Var1, "TemplateHint") 
    @Html.EditorFor(Function(m) m.Var2, "TemplateHint") 
    @Html.EditorFor(Function(m) m.Var3) 

End Using 

Phần của tôi trông như thế này ...

<div class="content"> 
    @@RenderBody() 
</div> 
15

Ngoài ra còn có một cách khác, không cần dùng một lần, điều này cũng đòi hỏi ít công việc hơn, tuyệt vời cho những người giúp đỡ nhỏ.

@helper MyHelper(string title, Func<object, object> markup) { 
    <div class="module"> 
     <h3>Title</h3> 
     <div> 
      <p>@markup.DynamicInvoke(this.ViewContext)</p> 
     </div> 
    </div> 
} 

Sử dụng helper này trông như thế này:

@MyHelper("This is my Title", 
    @<p>Here is my custom markup</p> 
) 

Hoặc với nhiều dòng:

@MyHelper("This is my Title", 
    @<text> 
     <p>More than one line</p> 
     <p>Of markup</p> 
    </text> 
) 

điều khiển Telerik MVC sử dụng thủ thuật này cho ví dụ để cho phép bạn thêm mã javascript của bạn tại tải tài liệu.

Đây cũng là một số đẹp example. Ngoài ra còn có một số thông tin here.

+0

Tôi thích ví dụ này. Xuất hiện để dễ thực hiện hơn nhiều. Bạn có thể giúp tôi giải quyết một vấn đề không? this.ViewContext không biên dịch vì phương thức MyHelper là static (ít nhất là tôi đã thiết lập nó trong helper của tôi). –

+1

Đáng ngạc nhiên là nó có xu hướng hoạt động tốt nếu bạn vượt qua nó null, nhưng có lẽ có thể có một số kịch bản phức tạp mà sẽ sụp đổ. Dù sao bạn sẽ có thể nhận được quyền truy cập vào ViewContext thông qua đối tượng Htmlhelper (nếu phương pháp tĩnh của bạn là phương pháp mở rộng html bạn nên có quyền truy cập vào nó) bằng cách sử dụng thuộc tính ViewContext. Nếu điều này không đúng, bạn có thể chuyển ViewContext sang phương thức thủ công. – slawek

+0

Cảm ơn bạn đã phản hồi. Đi qua null làm việc. Tôi nghĩ lý do mã của tôi không có quyền truy cập vào ViewContext là vì tôi đang xây dựng trang MVC thay vì ứng dụng. Nó hiện đang hoạt động. Tôi tin câu trả lời của bạn là tốt nhất vì nó đơn giản và hoạt động. –

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