2010-09-17 72 views
117

为什么我不能将html属性传递给EditorFor()?例如;ASP.NET MVC中EditorFor()的Html属性

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

我不想使用元数据

更新:解决的办法是从视图中调用这个:

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

和我的自定义EditorTemplates /字符串使用ViewData["Modifiable"]。 ascx其中我有一些视图逻辑,用于确定是将只读属性还是禁用属性添加到输入 传递到EditorFor()的匿名对象是一个名为的参数及其属性传递给ViewData集合中的编辑器模板。

+18

严重的是,仍然在MVC3这个限制没有意义,它真的很烦人。世界各地的人们正在花时间,用这些无聊的东西拉着头发。我将此发送给Microsoft Connect。 – 2012-09-21 14:14:30

+5

https://connect.microsoft.com/VisualStudio/feedback/details/764012/allow-htmlattributes-in-asp-net-mvc-editorfor – 2012-09-21 14:44:26

+3

它只是我,还是看起来像很多bs的东西应该太简单了? – 2012-12-11 01:08:56

回答

94

EditorFor适用于元数据,所以如果你想添加html属性你could always do it。另一种选择是简单地写一个自定义模板,并使用TextBoxFor

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

元数据将不起作用,因为html属性取决于模型中的其他属性,换句话说,域或viemodel逻辑应该确定html属性而不是静态元数据。或者我错过了这一点,我可以动态设置元数据吗? – 2010-09-17 13:05:51

+0

什么是PeriodType?这不是一个简单的属性?如果它是一个复杂的对象,您可以通过在'〜/ Views/ControllerName/EditorTemplates/SomeType.ascx'中放置一个部分来定制整个模板,其中'SomeType'是'PeriodType'属性的类型名称。 – 2010-09-17 13:06:30

+0

你的建议代码也意味着将整个模型传递给访问特定属性的部分模板,这意味着我对每个属性都有一个部分? – 2010-09-17 13:06:45

2

如果你不想使用元数据,您可以使用一个[UIHint("PeriodType")]属性装饰的财产,或者如果它是一个复杂的类型,你不必装饰任何东西。然后EditorFor将在EditorTemplates文件夹中查找PeriodType.aspx或ascx文件并使用它。

+0

谢谢,如果我的编辑器模板中的if/else只对某些字段是必需的,我可能会这样做 – 2010-09-17 13:36:18

+0

虽然你说你不能更改模型(不是你的代码) ,所以直接用UIHint装饰不会是一种选择。 – 2012-11-08 01:28:55

3

为什么不直接使用

@Html.DisplayFor(model => model.Control.PeriodType) 
+29

其中一个原因是DisplayFor未呈现输入,因此回发时丢失该值。 – ProfK 2012-04-25 06:11:42

+1

另一个原因是编辑器当前 - 但不总是锁定的特定情况,并且您想要传达数据可能是可编辑的 - 现在不是。 – Mir 2012-12-14 22:39:58

1
Html.TextBoxFor(model => model.Control.PeriodType, 
    new { @class="text-box single-line"}) 

你可以使用这样的;与Html.EditorFor相同的输出,你可以添加你的html属性

+0

除了'TextBoxFor',忽略任何你可能试图应用的'DisplayFormat'类型。 – 2012-12-11 00:57:00

1

我一直在荆棘与今天相同的问题绑定到一个可空的布尔复选框,因为我不能改变我的模型(不是我的代码)我不得不想出一个更好的方式来处理这个问题。这有点暴躁,但它应该适用于我可能遇到的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) 
+0

我添加了'Dictionary attribs = new Dictionary ();'和'attribs.Add(“tabindex”,“16”);'在这些'@()'块之一中我的页面顶部。然后,我在我的页面上执行了@ Html.CheckBox(“IsActive”,Model.IsActive.HasValue?Model.IsActive:false,attribs),它给了我一个错误:''System.Web.Mvc.HtmlHelper '不包含'CheckBox'的定义,并且最好的扩展方法重载'System.Web.Mvc.InputExtensions.CheckBox(System.Web.Mvc.HtmlHelper,string.bool,object)'有一些无效参数”。 – vapcguy 2014-10-25 02:22:55

1

刚刚创建自己的模板在视图/类型的共享/ 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语法。这就是我们滚动的方式。

2

您仍然可以使用EditorFor。只需将样式/无论哪个html属性都传递给ViewData。

@Html.EditorFor(model => model.YourProperty, new { style = "Width:50px" }) 

因为EditorFor使用模板来渲染,你可以重写你的属性的默认模板,只需通过style属性为ViewData的。

所以你EditorTemplate想以下几点:

@inherits System.Web.Mvc.WebViewPage<object> 

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

更新 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" } }) 

然后在模板

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

这个新功能完美地解决了四年前问的原始问题。 – CoderSteve 2014-10-30 17:24:13

+1

如果不是像这样的TextBoxFor和helpers我使用吨自定义编辑器模板,我不会说这是一个梦幻般的主意,将ViewData添加到他们每个人...... :( – Alexander 2016-05-26 11:05:42

38

由于MVC 5.1(不MVC 5.1需要简单类型),你现在可以做到以下几点:

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

http://www.asp.net/mvc/overview/releases/mvc51-release-notes#new-features

+0

上述链接已死亡。是在MVC 5.1,更多信息在这里:http://www.asp.net/mvc/overview/releases/mvc51-release-notes#new-features – 2014-03-03 15:55:04

+1

谢谢,我修复了链接以及。 – vtforester 2014-03-03 23:42:07

+1

如何合并htmlAttributes ? – 2014-04-07 19:11:16

5

现在ASP.Net MVC 5.1得到了一个bui以支持它。

From Release Notes

We now allow passing in HTML attributes in EditorFor as an anonymous object.

例如:

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

MVC 5.1和更高的溶液(将合并本地HtmlAttributes并在EditorTemplates定义):

共享\ EditorTemplates \ String.cshtml :

@Html.TextBoxFor(model => model, new { @class = "form-control", placeholder = ViewData.ModelMetadata.Watermark }.ToExpando().MergeHtmlAttributes(ViewData["htmlAttributes"].ToExpando())) 

扩展:

public static IDictionary<string, object> MergeHtmlAttributes(this ExpandoObject source1, dynamic source2) 
{ 
    Condition.Requires(source1, "source1").IsNotNull().IsLongerThan(0); 

    IDictionary<string, object> result = source2 == null 
     ? new Dictionary<string, object>() 
     : (IDictionary<string, object>) source2; 

    var dictionary1 = (IDictionary<string, object>) source1; 

    string[] commonKeys = result.Keys.Where(dictionary1.ContainsKey).ToArray(); 
    foreach (var key in commonKeys) 
    { 
     result[key] = string.Format("{0} {1}", dictionary1[key], result[key]); 
    } 

    foreach (var item in dictionary1.Where(pair => !result.ContainsKey(pair.Key))) 
    { 
     result.Add(item); 
    } 

    return result; 
} 

public static ExpandoObject ToExpando(this object anonymousObject) 
{ 
    IDictionary<string, object> anonymousDictionary = new RouteValueDictionary(anonymousObject); 
    IDictionary<string, object> expando = new ExpandoObject(); 
    foreach (var item in anonymousDictionary) 
     expando.Add(item); 
    return (ExpandoObject)expando; 
} 

public static bool HasProperty(this ExpandoObject expando, string key) 
{ 
    return ((IDictionary<string, object>)expando).ContainsKey(key); 
} 

用法:

@Html.EditorFor(m => m.PromotionalCode, new { htmlAttributes = new { ng_model = "roomCtrl.searchRoomModel().promoCode" }}) 
+1

谢谢,这是有效的。除了所有的data_xxx属性,我不得不用_替换_当把'source1'和'source2'作为'IDictionary '。 我做了这个函数: 'private static IDictionary ToHtmlAttributesDictionary(this IEnumerable > dico){return dico.ToDictionary(s => s.Key.Replace('_',' - '),s => s.Value );}' – 2014-10-31 10:50:26

1

在我来说,我试图创造一种可以接受的附加属性的HTML5号码输入编辑模板。一个整齐的办法是写自己的HTML助手,但因为我已经有我的.ascx模板,我用这种方法去:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %> 
<input id="<%= Regex.Replace(ViewData.TemplateInfo.GetFullHtmlFieldId(""), @"[\[\]]", "_") %>" name="<%= ViewData.TemplateInfo.HtmlFieldPrefix %>" type="number" value="<%= ViewData.TemplateInfo.FormattedModelValue %>" 
<% if (ViewData["attributes"] != null) 
    { 
     Dictionary<string, string> attributes = (Dictionary<string, string>)ViewData["attributes"]; 
     foreach (string attributeName in attributes.Keys){%> 
     <%= String.Format(" {0}=\"{1}\"", attributeName, attributes[attributeName])%> 
     <% } 
    } %> /> 

这丑陋位创建许多类型的输入和查找一个ViewData字典与关键的“属性”。它将遍历字典,将其键/值对添加为属性。 ID属性中的正则表达式不相关,因为在集合中使用时,GetFullHtmlFieldId()返回一个包含方括号[]的ID,它通常会作为下划线转义。

这个模板,然后调用这样的:

Html.EditorFor(m => m.Quantity, "NumberField", new { attributes = new Dictionary<string, string>() { { "class", "txtQuantity" } } } 

冗长,但它的作品。您可以使用模板中的反射来将属性名称用作属性名称,而不是使用字典。

4

以下是在MVC 5.1的VB.Net代码语法HTML属性EditorFor

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

设置在所述控制器使用ViewData条件

ViewData["Modifiable"] = model.recProcessed; 

然后,在使用此可视数据编辑器模板来设置控件的html属性

@Html.RadioButton(prefix, li.Value, li.Selected, @ViewData["Modifiable"].ToString().ToLower() == "true" ? (object)new { @id = li.Value, @disabled = "disabled" } : new { @id = li.Value })