2016-10-20 187 views
1

我一直在为MVC 5网站做一个扩展方法。其基本思想是它将为我们的输入组创建标记(即放入标签,输入和验证消息)。这些组将具有一些标准的HTML和CSS类,这些类将始终存在。到目前为止,这是我所拥有的,而且工作正常。如何使用EditorFor在MVC 5中添加动态HTML属性?

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类“的形式控制”文本框)。但是,如果我使用合并属性的代码,那么与没有第二个参数调用EditorFor(即,我的文本框在未设置任何CSS类时出现)相比,我没有任何不同。

所以我尝试了一些其他的东西,比如将合并后的属性投射到object。不用找了。我试图将合并的属性转换为ExpandoObject。没有。在传入之前试图将ExpandoObject转换为object。没有区别。

有没有办法做到这一点?这似乎很奇怪,这只适用于匿名类型,而大多数其他方法(TextBoxFor等)可以采用属性字典。

(我可以在此时想到的唯一的事情就是开始重写/覆盖默认模板以某种方式适应这一点。如果我没有我宁愿不走这一步。)

回答

0

我想你需要从匿名更改htmlAttributes到RouteValueDictionary

尝试是这样的:

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

为什么一个RouteValueDictionary有所作为?这与路由根本没有关系。 – Becuzz

+0

https://cpratt.co/html-editorfor-and-htmlattributes/ – RitchieD

+0

如果你阅读那篇文章,它指出,在MVC 5.1中,他们通过增加使用匿名对象的能力来解决我遇到的问题使用它。有了这个修复,他们碰巧使用了一个RouteValueDictionary(正如文章所承认的,一旦它的用途扩大,它就成了一个可怕的名字)。但从MVC 5开始,实现这一目标的唯一方法是覆盖默认模板。因此,您的解决方案实际上并未解决MVC 5中的问题。在这种情况下,“解决方案”将升级到MVC 5.1或更高版本。 – Becuzz