ASP.NET MVC - 在不重写方法的情况下扩展TextBoxFor

时间:2011-06-01 13:36:58

标签: asp.net-mvc-3

有没有办法在输出中使用扩展方法扩展基本的html助手(TextBoxForTextAreaFor等),而不是仅仅重写整个方法?例如,添加...

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

我知道我已经可以使用以下内容实现这一目标了。

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

但是,当您必须开始添加大量属性时,管理变得笨拙和令人沮丧。是否有任何方法可以为这些内容添加扩展,而无需为每个小细节传递htmlAttributes

2 个答案:

答案 0 :(得分:9)

正如@AaronShockley所说,因为TextBoxFor()返回MvcHtmlString,因此开发修改输出的“流体API”风格的唯一选择是对返回的MvcHtmlString进行操作通过辅助方法。执行此操作的一种略微不同的方式,我认为接近您所使用的将是使用“属性构建器”对象,如下所示:

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

    public string Class { get; set; }
}

...并设置如下的扩展方法:

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

然后,您可以在视图中执行以下操作:

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

这为您提供了输入属性的强类型和智能感知,您可以通过向适当的MvcInputBuilder子类添加属性来为每个扩展方法自定义。

答案 1 :(得分:6)

所有基本的html助手都返回System.Web.Mvc.MvcHtmlString类型的对象。您可以为该类设置扩展方法。这是一个例子:

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

然后您可以在以下视图中使用这些:

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

要制作修改呈现的HTML标记上的属性的扩展方法,您必须将结果转换为字符串,然后查找并替换您要查找的值。

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

idname属性总是由html助手添加,但是如果你想使用可能不存在的属性(你必须添加它们而不是仅仅替换它们)他们),你需要修改代码。