136

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

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

我不想使用元数据

更新:解决方案是从视图中调用它:

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

ViewData["Modifiable"]在我的自定义 EditorTemplates/String.ascx 中使用,其中我有一些视图逻辑,用于确定是否向输入添加只读和/或禁用属性传入的匿名对象EditorFor()是一个调用的参数additionalViewData,其属性被传递给编辑器模板ViewData收藏。

4

14 回答 14

125

更新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"])
于 2013-05-23T05:37:20.710 回答
99

EditorFor使用元数据,所以如果你想添加 html 属性,你总是可以这样做。另一种选择是简单地编写一个自定义模板并使用TextBoxFor

<%= Html.TextBoxFor(model => model.Control.PeriodType, 
    new { disabled = "disabled", @readonly = "readonly" }) %>    
于 2010-09-17T12:52:01.930 回答
43

从 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

于 2013-12-10T16:02:36.860 回答
6

现在ASP.Net MVC 5.1内置了对它的支持。

来自发行说明

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

例如:

@Html.EditorFor(model => model, 
              new { htmlAttributes = new { @class = "form-control" }, })
于 2014-05-13T09:33:29.127 回答
5

这是MVC 5.1 EditorFor中 html 属性的VB.Net 代码语法

@Html.EditorFor(Function(x) x.myStringProp, New With {.htmlAttributes = New With {.class = "myCssClass", .maxlength="30"}}))
于 2015-05-29T14:57:34.830 回答
3

为什么不直接使用

@Html.DisplayFor(model => model.Control.PeriodType)
于 2010-12-29T22:48:08.387 回答
2

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

于 2010-09-17T13:34:02.020 回答
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)
于 2012-08-14T19:35:16.490 回答
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"] })
于 2013-01-29T11:08:53.460 回答
1
Html.TextBoxFor(model => model.Control.PeriodType, 
    new { @class="text-box single-line"})

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

于 2012-07-26T16:01:14.503 回答
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 语法。这就是我们滚动的方式。

于 2012-11-08T01:48:37.207 回答
1

在我的例子中,我试图创建一个可以接收附加属性的 HTML5 数字输入编辑器模板。一种更简洁的方法是编写自己的 HTML Helper,但由于我已经有了 .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 属性中的 Regex 是不相关的,因为在集合中使用时,它会GetFullHtmlFieldId()返回一个包含方括号的 id [],它通常会转义为下划线。

然后像这样调用这个模板:

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

冗长,但它有效。您可能可以在模板中使用反射来使用属性名称作为属性名称,而不是使用字典。

于 2014-09-12T21:33:36.430 回答
1

ViewData在控制器中设置使用条件

ViewData["Modifiable"] = model.recProcessed;

然后在编辑器模板中使用这个viewdata来设置控件的html属性

@Html.RadioButton(prefix, li.Value, li.Selected, @ViewData["Modifiable"].ToString().ToLower() == "true" ? (object)new  { @id = li.Value, @disabled = "disabled" } : new { @id = li.Value })
于 2015-07-31T09:39:26.863 回答
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" }})
于 2014-08-26T06:26:13.630 回答