2011-06-01 25 views
8

¿Hay alguna manera posible de ampliar los ayudantes html básicos (TextBoxFor, TextAreaFor, etc.) usando métodos de extensión en su salida, en lugar de simplemente volver a escribir los métodos completos ¿completamente? Por ejemplo, la adición de ...ASP.NET MVC - Extender TextBoxFor sin volver a escribir el método

@Html.TextBoxFor(model => model.Name).Identity("idName")

sé que puedo lograr esto usando la siguiente, ya ..

@Html.TextBoxFor(model => model.Name, new { @id = "idName" })

Pero eso consigue torpe y frustrante para manejar cuando se tiene para comenzar a agregar muchas propiedades. ¿Hay alguna forma de agregar extensiones a estos inherentemente sin pasar por htmlAttributes por cada pequeño detalle?

Respuesta

9

Como dice @AaronShockley, porque TextBoxFor() devuelve un MvcHtmlString, su única opción para el desarrollo de un estilo 'API fluida' de la modificación de la salida sería para funcionar en las MvcHtmlString s devueltos por los métodos de ayuda. Una forma un poco diferente de hacer esto que creo que se aproxima a lo que está buscando sería el uso de un objeto "propiedad del constructor, así:

public class MvcInputBuilder 
{ 
    public int Id { get; set; } 

    public string Class { get; set; } 
} 

... y establecer métodos de extensión como esta:

public static MvcHtmlString TextBoxFor<TModel, TProp>(
    this HtmlHelper<TModel> htmlHelper, 
    Expression<Func<TModel, TProp>> expression, 
    params Action<MvcInputBuilder>[] propertySetters) 
{ 
    MvcInputBuilder builder = new MvcInputBuilder(); 

    foreach (var propertySetter in propertySetters) 
    { 
     propertySetter.Invoke(builder); 
    } 

    var properties = new RouteValueDictionary(builder) 
     .Select(kvp => kvp) 
     .Where(kvp => kvp.Value != null) 
     .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); 

    return htmlHelper.TextBoxFor(expression, properties); 
} 

a continuación, puede hacer cosas como esta en su Vista:

@this.Html.TextBoxFor(
    model => model.Name, 
    p => p.Id = 7, 
    p => p.Class = "my-class") 

esto le da una gran escritura y intelliSense para las propiedades de entrada, que se puede personalizar para cada método de extensión mediante la adición de pro depende de una subclase MvcInputBuilder adecuada.

6

Todos los helpers html básicos devuelven un objeto del tipo System.Web.Mvc.MvcHtmlString. Puede configurar métodos de extensión para esa clase. He aquí un ejemplo:

public static class MvcHtmlStringExtensions 
{ 
    public static MvcHtmlString If(this MvcHtmlString value, bool check) 
    { 
     if (check) 
     { 
      return value; 
     } 

     return null; 
    } 

    public static MvcHtmlString Else(this MvcHtmlString value, MvcHtmlString alternate) 
    { 
     if (value == null) 
     { 
      return alternate; 
     } 

     return value; 
    } 
} 

continuación, puede utilizar estos en una vista como:

@Html.TextBoxFor(model => model.Name) 
    .If(Model.Name.StartsWith("A")) 
    .Else(Html.TextBoxFor(model => model.LastName) 

Para que los métodos de extensión que modifican los atributos en la etiqueta HTML representado, tendrá que convertir el resultado a una cadena, y encuentre y reemplace el valor que está buscando.

using System.Text.RegularExpressions; 

public static MvcHtmlString Identity(this MvcHtmlString value, string id) 
{ 
    string input = value.ToString(); 
    string pattern = @"(?<=\bid=")[^"]*"; 
    string newValue = Regex.Replace(input, pattern, id); 
    return new MvcHtmlString(newValue); 
} 

public static MvcHtmlString Name(this MvcHtmlString value, string id) 
{ 
    string input = value.ToString(); 
    string pattern = @"(?<=\bname=")[^"]*"; 
    string newValue = Regex.Replace(input, pattern, id); 
    return new MvcHtmlString(newValue); 
} 

Los id y name atributos siempre se agregan por los ayudantes del HTML, pero si se quiere trabajar con atributos que pueden no estar allí (y usted tendrá que añadirlos en lugar de sólo la sustitución de ellos), se Necesitaremos modificar el código.

Cuestiones relacionadas