2014-05-07 17 views
27

Mam funkcję pomocnika Razor, która tworzy panel HTML wielokrotnego użytku, który zapisuje, że piszę ten sam kod HTML w kółko.Tworzenie komponentów widoku HTML wielokrotnego użytku przy użyciu narzędzia Razor w środowisku 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> 
} 

Zastanawiam się, czy możliwe jest ponowne użycie tego pomocnika do wypełnienia .panel-content z większą HTML, aby umożliwić większą elastyczność i ponowne wykorzystanie kodu - podobny coś jak poniżej:

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

Podczas korzystania z .NET MVC zauważyłem, że Html.BeginForm() robi podobnie podczas pakowania kodu w deklaracji @using w deklaracji Html.BeginForm, tak jak:

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

Ale czy można tego dokonać przy użyciu metod @helper? Jeśli nie, czy jest możliwe utworzenie rozszerzenia HtmlHelper, aby zrobić coś podobnego, jak robi to metoda Html.BeginForm()?

Można zrobić bardzo podobną rzecz, używając składni @section jak widać here

enter image description here

To wydaje się czymś, co byłoby bardzo przydatne, aby móc to zrobić, i dziwne, że nie ma łatwy sposób zrób to na poziomie komponentu.

Odpowiedz

34

Istnieją dwa sposoby uzyskania wymaganej funkcjonalności.

1. @helper

Tworzenie @helper który akceptuje cokolwiek parametry trzeba plus funkcja (pojedynczy parametr obiektu, powraca Object):

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

Zastosowanie:

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

Twoja funkcja może również akceptować parametry, na przykład here.

2.HtmlHelper metodę rozszerzenia

Dodaj następujący kod w dowolnym miejscu w projekcie:

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

Zastosowanie:

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

Metoda rozszerzenie pisze bezpośrednio do kontekstu. Sztuką jest zwrócenie obiektu jednorazowego, którego metoda Dispose zostanie wykonana pod koniec bloku using.

+0

Głosuję na opcję 2. – MikeSW

+0

Doskonały, drugi działa jak czar! Dziękuję za poświęcenie czasu na napisanie tak dokładnej odpowiedzi. –

+0

Dobra odpowiedź. Wolę drugi. – pixparker

1

Nie wiem, czy można to zrobić metodami @helper, ale rozszerzenia na pewno będą dostępne pod HtmlHelper. Wspominałeś o tym, że jest to prawdopodobnie najbardziej znany model - wszystko, co musisz zrobić, to zwrócić obiekt, który implementuje IDisposable, co oznacza, że ​​po wywołaniu metody Dispose() po prostu wywołuje bezpłatną metodę Html.EndForm(), aby dodać odpowiednie znaczniki zamykające.

Byłoby bardzo proste zrobić coś podobnego do kodu HTML. Możesz zobaczyć kod źródłowy do ASP.NET MVC HtmlHelpers na http://aspnetwebstack.codeplex.com/ - kod BeginForm() może być konkretnie viewed here.

Powiązane problemy