如何使用EditorFor在MVC 5中添加动态HTML属性?

时间:2016-10-20 16:14:54

标签: c# asp.net-mvc-5.1

我一直致力于为MVC 5网站制作扩展方法。基本思想是它将为我们的输入组创建标记(即放入标签,输入和验证消息)。这些组将具有一些始终存在的标准HTML和CSS类。到目前为止,这就是我所拥有的,并且工作正常。

public static MvcHtmlString CreateEditorForGroup<TModel, TProperty>(this HtmlHelper<TModel> helper,
    Expression<Func<TModel, TProperty>> expression)
{
    TagBuilder editorLabel = new TagBuilder("span");
    editorLabel.AddCssClass("form-label");
    editorLabel.InnerHtml += helper.LabelFor(expression);

    TagBuilder wrappingDiv = new TagBuilder("div");
    wrappingDiv.InnerHtml = editorLabel.ToString() + helper.EditorFor(expression, new { htmlAttributes = new { @class = "form-control" }}).ToString() + helper.ValidationMessageFor(expression).ToString();
    return new MvcHtmlString(wrappingDiv.ToString());
}

我还需要进一步扩展它以允许传入额外的自定义HTML属性(其他CSS类,数据属性等)。所以我到目前为止:

public static MvcHtmlString CreateEditorForGroup<TModel, TProperty>(this HtmlHelper<TModel> helper,
    Expression<Func<TModel, TProperty>> expression, object htmlAttributesForEditor = null)
{
    TagBuilder editorLabel = new TagBuilder("span");
    editorLabel.AddCssClass("form-label");
    editorLabel.InnerHtml += helper.LabelFor(expression);

    var editorHtmlAttributes = MergeHtmlAttributes(htmlAttributesForEditor, new { @class = "form-control" });

    TagBuilder wrappingDiv = new TagBuilder("div");
    wrappingDiv.InnerHtml = editorLabel.ToString() + helper.EditorFor(expression, new { htmlAttributes = editorHtmlAttributes }).ToString() + helper.ValidationMessageFor(expression);
    return new MvcHtmlString(wrappingDiv.ToString());
}

(不要担心MergeHtmlAttributes的定义。目前它工作正常并返回IDictionary<string, object>。)因为我所做的所有研究(以及我自己的测试)都表明我可以做到以下

helper.EditorFor(expression, new { htmlAttributes = new { @class = "form-control" }})

并获得预期的结果(在我的例子中,一个带有css类“form-control”的文本框)。但是如果我使用合并属性的代码,我没有得到任何不同,如果我没有第二个参数调用EditorFor(即我的文本框没有设置任何CSS类)。

所以我尝试了其他一些东西,比如将合并的属性转换为object。没变。我尝试将合并的属性转换为ExpandoObject。没有。尝试将ExpandoObject转换为object,然后再将其传入。没有区别。

有没有办法实现这个目标?看起来很奇怪,这只适用于匿名类型,而大多数其他方法(TextBoxFor等)都可以使用属性字典。

(我现在唯一能想到的就是开始重写/覆盖默认模板以适应这种方式。如果我不需要,我宁愿不去那条路。)

1 个答案:

答案 0 :(得分:0)

我认为您需要将htmlAttributes从匿名更改为RouteValueDictionary

尝试这样的事情:

RouteValueDictionary htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(editorHtmlAttributes);
... + helper.EditorFor(expression, new { htmlAttributes = htmlAttributes }).ToString() + ...