ASP.NET MVC中EditorFor()的HTML属性

139

为什么我不能将HTML属性传递给EditorFor()?例如:

<%= Html.EditorFor(model => model.Control.PeriodType, 
    new { disabled = "disabled", readonly = "readonly" }) %>

我不想使用元数据

更新:解决方案是从视图调用此函数:

 <%=Html.EditorFor( model => model.Control.PeriodEndDate, new {Modifiable=model.Control.PeriodEndDateModifiable})%>

我希望在自定义的EditorTemplates/String.ascx中使用ViewData["Modifiable"],并进行一些视图逻辑,以确定是否向输入添加readonly和/或disabled属性。传递给EditorFor()的匿名对象是一个名为additionalViewData的参数,其属性将在ViewData集合中传递到编辑器模板中。


23
严肃地说,在MVC3中仍然存在这种限制是没有意义的,而且真的很烦人。全世界的人们正在花费时间和精力来应对这种无聊的限制。我将把这个问题发送到Microsoft Connect。 - Junior Mayhé
5
允许在ASP.NET MVC EditorFor中使用HTML属性。链接地址:https://connect.microsoft.com/VisualStudio/feedback/details/764012/allow-htmlattributes-in-asp-net-mvc-editorfor - Junior Mayhé
3
是只有我,还是这似乎对于应该非常简单的事情来说有太多废话了? - Eric K
也许这会对你有所帮助:使用CSS类和HTML属性实现EditorFor - FunThom
可能是[EditorFor()和html属性]的重复问题。 (https://dev59.com/V3I-5IYBdhLWcg3w483k) - Gyrfalcon
14个回答

126

更新: MVC 5.1现在直接支持以下方法,因此它也适用于内置编辑器。 http://www.asp.net/mvc/overview/releases/mvc51-release-notes#new-features (这要么是伟大思维的巧合,要么是他们读了我的答案:)

如果您正在使用自己的编辑器模板或使用MVC 5.1,则现在直接支持内置编辑器的以下方法。

@Html.EditorFor(modelItem => item.YourProperty, 
  new { htmlAttributes = new { @class="verificationStatusSelect", style = "Width:50px"  } })

然后在您的模板中(对于MVC 5.1中的简单类型不是必需的)

@Html.TextBoxFor(m => m, ViewData["htmlAttributes"])

5
这个新功能完美地解决了四年前提出的问题。 - CoderSteve
1
如果我使用大量自定义编辑器模板而不是像TextBoxFor和类似的辅助工具,那么在每个模板中添加ViewData[...]并不是一个好主意... :( - Alexander

100

EditorFor使用元数据,如果您想添加HTML属性,可以尝试这个方法。另一种选择是编写自定义模板并使用TextBoxFor

<%= Html.TextBoxFor(model => model.Control.PeriodType, 
    new { disabled = "disabled", @readonly = "readonly" }) %>    

元数据无法工作,因为HTML属性取决于模型中的其他属性,换句话说,领域或视图模型逻辑应该确定HTML属性,而不是静态元数据。或者我理解有误,我能动态设置元数据吗? - Typo Johnson
2
我明白你的意思了。我可以使用<%=Html.EditorFor(model => model.Control.PeriodEndDate, new {Modifiable=model.Control.PeriodEndDateModifiable})%>,并在我的自定义EditorTemplates/String.ascx中使用ViewData["PeriodEndDateModifiable"]。谢谢。 - Typo Johnson
真的很无聊的解决方法。大家,投赞成票!http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/3183610-allow-htmlattributes-in-asp-mvc-editorfor - Junior Mayhé
1
@JuniorMayhé,我不会把这看作是一个无聊的限制。如果你仔细考虑一下,你就会明白这是有道理的。事实上,EditorFor助手的整个关键在于你可以拥有一个相应的模板。这个模板可以包含任何标记。不一定是单个元素。例如,为包含3个div的编辑器模板定义@class将没有任何意义。Html.TextBoxFor助手允许你定义这个是因为你知道这个助手生成了一个文本框,所以给输入元素定义一个类是有意义的。 - Darin Dimitrov
确实,为3个div创建一个类没有意义。除非EditorFor没有要查找的模板。更好地处理html属性的可能性会更好,避免我们今天在互联网上看到的解决方法。想象一下一个帮助程序:EditorFor(m=>m.YourField, renderAsSingleInput, htmlAttributesHere),这将为需要坚持使用EditorFor方法的人节省时间。 - Junior Mayhé
显示剩余3条评论

43

以上链接已失效。此功能可在MVC 5.1中使用,更多信息请参见:http://www.asp.net/mvc/overview/releases/mvc51-release-notes#new-features - Alaa Masoud
1
谢谢,我也修复了链接。 - vtforester
2
如何合并htmlAttributes? - Bart Calixto
这仅适用于内置/默认的“EditorFor”模板。如果您实现自己的模板,您必须遵循AntonK的答案。 - mxmissile

6
现在,ASP.Net MVC 5.1 内置支持它。

来自发布说明

现在我们允许在EditorFor中传递HTML属性作为匿名对象。

例如:

@Html.EditorFor(model => model, 
              new { htmlAttributes = new { @class = "form-control" }, })

5

这里是用VB.Net编写的在MVC 5.1中使用EditorFor时的html属性语法

@Html.EditorFor(Function(x) x.myStringProp, New With {.htmlAttributes = New With {.class = "myCssClass", .maxlength="30"}}))

3
为什么不直接使用?
@Html.DisplayFor(model => model.Control.PeriodType)

32
一个原因是DisplayFor不会呈现输入,所以在提交后该值会丢失。 - ProfK
2
另一个原因是编辑器当前被锁定但不总是被锁定的特定情况下,您希望传达数据可能是可编辑的 - 只是现在不行。 - Mir

2
我今天遇到了一个问题,需要处理绑定到可空布尔值的复选框。由于我不能更改我的模型(不是我的代码),因此我必须想出一种更好的处理方法。这有点暴力,但它应该适用于我可能遇到的99%的情况。显然,您需要手动填充每个输入类型的有效属性,但我认为我已经为复选框获取了所有属性。
在我的Boolean.cshtml编辑器模板中:
@model bool?

@{
    var attribs = new Dictionary<string, object>();
    var validAttribs = new string[] {"style", "class", "checked", "@class",
        "classname","id", "required", "value", "disabled", "readonly", 
        "accesskey", "lang", "tabindex", "title", "onblur", "onfocus", 
        "onclick", "onchange", "ondblclick", "onmousedown", "onmousemove", 
        "onmouseout", "onmouseover", "onmouseup", "onselect"};
    foreach (var item in ViewData) 
    {
        if (item.Key.ToLower().IndexOf("data_") == 0 || item.Key.ToLower().IndexOf("aria_") == 0) 
        {
            attribs.Add(item.Key.Replace('_', '-'), item.Value);
        } 
        else 
        {
            if (validAttribs.Contains(item.Key.ToLower()))
            {
                attribs.Add(item.Key, item.Value);
            }
        }
    }
}

@Html.CheckBox("", Model.GetValueOrDefault(), attribs)

我在页面顶部的一个 @( ) 块中添加了 Dictionary<string,string> attribs = new Dictionary<string,string>();attribs.Add("tabindex","16");。然后我在页面上使用了 @Html.CheckBox("IsActive", Model.IsActive.HasValue ? Model.IsActive : false, attribs),但是它给了我一个错误:"'System.Web.Mvc.HtmlHelper<MyProject.Models.MyObject>' 不包含 'CheckBox' 的定义,而最佳的扩展方法重载 'System.Web.Mvc.InputExtensions.CheckBox(System.Web.Mvc.HtmlHelper, string.bool, object)' 具有一些无效的参数"。 - vapcguy

2
您仍然可以使用EditorFor。只需将样式/任何html属性作为ViewData传递即可。
@Html.EditorFor(model => model.YourProperty, new { style = "Width:50px" })

由于EditorFor使用模板进行渲染,您可以覆盖属性的默认模板,并将样式属性作为ViewData传递。
因此,您的EditorTemplate应如下所示:
@inherits System.Web.Mvc.WebViewPage<object>

@Html.TextBoxFor(m => m, new { @class = "text ui-widget-content", style=ViewData["style"] })

2

如果您不想使用元数据,可以使用[UIHint("PeriodType")]属性来装饰属性,如果是复杂类型,则无需装饰任何内容。然后,编辑器将在EditorTemplates文件夹中查找PeriodType.aspx或ascx文件并使用它代替。


谢谢,如果我的编辑器模板中的if/else仅适用于特定字段,则我可能会这样做。 - Typo Johnson
我以为你说过你不能更改模型(而不是你的代码),所以直接用UIHint装饰可能不是一个选项。 - Darrel Lee

1

只需在 Views/Shared/EditorTemplates/MyTypeEditor.vbhtml 中创建自己的模板即可。

@ModelType MyType

@ModelType MyType
@Code
    Dim name As String = ViewData("ControlId")
    If String.IsNullOrEmpty(name) Then
        name = "MyTypeEditor"
    End If
End Code

' Mark-up for MyType Editor
@Html.TextBox(name, Model, New With {.style = "width:65px;background-color:yellow"})

通过模型属性从您的视图调用编辑器:

@Html.EditorFor(Function(m) m.MyTypeProperty, "MyTypeEditor", New {.ControlId = "uniqueId"})

不好意思,VB语法是我们的惯用方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接