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

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

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

我不想用元数据

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

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

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

252183 次浏览

EditorFor使用元数据,因此如果您想添加 html 属性,请使用 总能做到。另一种选择是简单地编写一个自定义模板并使用 TextBoxFor:

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

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

为什么不直接用呢

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

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

我今天一直在纠结同样的问题,为了一个绑定到可为空的 bool 的复选框,既然我不能改变我的模型(不是我的代码) ,我必须想出一个更好的方法来处理这个问题。这有点暴力,但对我可能遇到的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)

只需在视图/共享/编辑模板/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"})

使用 model 属性从视图调用编辑器:

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

请原谅 VB 的语法,这就是我们的工作方式。

您仍然可以使用 EditorFor。

@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"] })

更新 MVC 5.1现在直接支持以下方法,因此它也适用于内置编辑器。 < a href = “ http://www.asp.net/MVC/view/release/mvc51-release-note # new-Features”> 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"])

从 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

现在 ASP.Net MVC 5.1得到了一个内置的支持。

从发行说明

我们现在允许以匿名方式在 EditorFor 中传入 HTML 属性 对象。

例如:

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

MVC 5.1及更高的解决方案(将合并本地 HtmlAttritribute 并在 EditorTemplate 中定义) :

共享编辑器模板 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" }})

在我的案例中,我试图创建一个可以接收额外属性的 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])%>
<% }
} %> />

这个丑陋的部分创建了一个数字类型输入,并查找带有关键“属性”的 ViewDataDictionary。它将遍历字典,添加其键/值对作为属性。ID 属性中的 Regex 是不相关的,因为在集合中使用时,GetFullHtmlFieldId()返回一个包含方括号 []的 ID,它通常会以下划线的形式转义。

这个模板的名字是这样的:

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

很冗长,但很管用。您可以使用模板中的反射来使用属性名作为属性名,而不是使用字典。

下面是 MVC 5.1中的 html 属性 EditorFor 的 网络代码语法

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

在控制器中使用 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 })