2011-08-25 20 views
22

Chcę utworzyć pomocnika, który doda zawartość między nawiasami, podobnie jak Helper.BeginForm(). Nie miałbym nic przeciwko stworzeniu Begin, End dla mojego pomocnika, ale jest to całkiem proste i łatwe do zrobienia w ten sposób.Tworzenie pomocnika maszynki do golenia MVC3 podobnego do Helper.BeginForm()

zasadzie to, co usiłuję zrobić jest zawijany zawartości między tymi tagami więc są renderowane już sformatowane

coś

@using Html.Section("full", "The Title") 
{ 
This is the content for this section 
<p>More content</p> 
@Html.TextFor("text","label") 
etc etc etc 
} 

parametry „full” jest id css dla tego div i " tytuł "to tytuł sekcji.

Czy istnieje lepszy sposób osiągnięcia tego niż wykonanie tego, co próbuję zrobić?

z góry dzięki za pomoc.

Odpowiedz

36

Jest to całkowicie możliwe. Sposób w MVC z takimi obiektami jak Helper.BeginForm polega na tym, że funkcja musi zwrócić obiekt, który implementuje IDisposable.

Parametr IDisposable interface definiuje pojedynczą metodę o nazwie Dispose, która jest wywoływana tuż przed zbiorem śmieci.

W języku C# parametr using pomaga ograniczyć zakres obiektu i usunąć go z pamięci, gdy tylko opuszcza zakres. Używanie jej z IDisposable jest naturalne.

Będziesz chciał zaimplementować klasę Section, która implementuje IDisposable. Będzie musiał wyrenderować otwarty znacznik dla twojej sekcji, gdy zostanie skonstruowany, i wyrenderować znacznik zamykający, gdy zostanie usunięty. Na przykład:

public class MySection : IDisposable { 
    protected HtmlHelper _helper; 

    public MySection(HtmlHelper helper, string className, string title) { 
     _helper = helper; 
     _helper.ViewContext.Writer.Write(
      "<div class=\"" + className + "\" title=\"" + title + "\">" 
     ); 
    } 

    public void Dispose() { 
     _helper.ViewContext.Writer.Write("</div>"); 
    } 
} 

Teraz, gdy typ jest dostępny, można rozszerzyć HtmlHelper.

public static MySection BeginSection(this HtmlHelper self, string className, string title) { 
    return new MySection(self, className, title); 
} 
+0

powinieneś zmienić swoje imię i nazwisko na whatgoodisadispose !!! :) dziękuję bardzo. Wiedziałem, że musisz zaimplementować iDisposable, aby klasa była używana przy użyciu {}, ale NIGDY nie pomyślałeś o tym przez jedną sekundę. jeszcze raz bardzo dziękuję –

+1

Ah, pisarz, to załatwiło sprawę. –

4

Oto mały użytek, który napisałem, aby to zrobić. Jest trochę bardziej ogólny, więc możesz go użyć do dowolnego tagu i dowolnych atrybutów. Jest skonfigurowany jako metoda rozszerzenia na HtmlHelper, dzięki czemu można go używać bezpośrednio z urządzenia Razor, jak również z kodu.

public static class WrapUtil 
{ 
    public static IDisposable BeginWrap(this HtmlHelper helper, string tag, object htmlAttributes) 
    { 
     var builder = new TagBuilder(tag); 
     var attrs = GetAttributes(htmlAttributes); 
     if (attrs != null) 
     { 
      builder.MergeAttributes<string, object>(attrs); 
     } 
     helper.ViewContext.Writer.Write(builder.ToString(TagRenderMode.StartTag)); 

     return new WrapSection(helper, builder); 
    } 

    private static IDictionary<string, object> GetAttributes(object htmlAttributes) 
    { 
     if (htmlAttributes == null) 
     { 
      return null; 
     } 
     var dict = htmlAttributes as IDictionary<string, object>; 
     if (dict != null) 
     { 
      return dict; 
     } 
     return HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes); 
    } 

    private class WrapSection : IDisposable 
    { 
     private readonly HtmlHelper _Helper; 
     private readonly TagBuilder _Tag; 

     public WrapSection(HtmlHelper helper, TagBuilder tag) 
     { 
      _Helper = helper; 
      _Tag = tag; 
     } 

     public void Dispose() 
     { 
      _Helper.ViewContext.Writer.Write(_Tag.ToString(TagRenderMode.EndTag)); 
     } 
    } 
} 
Powiązane problemy