2011-08-25 22 views
22

Quiero crear un helper que pueda agregar contenido entre corchetes al igual que lo hace Helper.BeginForm(). No me importaría crear un Begin, End para mi ayudante, pero es bastante simple y fácil hacerlo de esa manera.Creando MVC3 Razor Helper como Helper.BeginForm()

básicamente lo que estoy tratando de hacer es envolver el contenido entre estas etiquetas para que se prestan ya formateados

algo así como

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

los parámetros de "lleno" es el identificador de CSS para que div y " el título "es el título de la sección.

¿Hay una manera mejor de lograr esto que hacer lo que estoy tratando de hacer?

gracias de antemano por cualquier ayuda.

Respuesta

36

Es totalmente posible. La forma en que esto se hace en MVC con cosas como Helper.BeginForm es que la función debe devolver un objeto que implemente IDisposable.

El IDisposable interface define un único método llamado Dispose que se llama justo antes de que el objeto se recoja como basura.

En C#, la palabra clave using es útil para restringir el alcance de un objeto y para recolectarlo en cuanto sale del ámbito. Entonces, usarlo con IDisposable es natural.

Deseará implementar una clase Section que implementa IDisposable. Deberá representar la etiqueta abierta para su sección cuando esté construida, y renderizará la etiqueta de cierre cuando se elimine. Por ejemplo:

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

Ahora que el tipo está disponible, puede extender el HtmlHelper.

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

debe cambiar su nombre a whatgoodisadisponer !!! :) muchas gracias. Sabía que debes implementar iDisposable para usar una clase con {}, pero NUNCA pensé en esto por un segundo. muchas gracias una vez más –

+1

Ah, escritor, eso fue lo que hizo el truco. –

4

Aquí hay una pequeña utilidad que escribí para hacer esto. Es un poco más genérico, así que puedes usarlo para cualquier etiqueta y con cualquier atributo. Está configurado como un método de extensión en HtmlHelper para que pueda usarlo desde dentro de Razor así como desde dentro del código.

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)); 
     } 
    } 
} 
Cuestiones relacionadas