TextBoxFor与EditorFor,以及htmlAttributes与additionalViewData

G-u*_*nit 30 asp.net-mvc-3

我创建了一个默认的MVC 3项目(使用razor),以演示一个问题.

在登录页面上,有一行:

@Html.TextBoxFor(m => m.UserName)
Run Code Online (Sandbox Code Playgroud)

如果我改为:

@Html.TextBoxFor(m => m.UserName, new { title = "ABC" })
Run Code Online (Sandbox Code Playgroud)

然后它呈现为(带有title属性):

<input data-val="true" data-val-required="The User name field is required." id="UserName" name="UserName" title="ABC" type="text" value="" />
Run Code Online (Sandbox Code Playgroud)

但是,如果我使它成为EditorFor:

 @Html.EditorFor(m => m.UserName, new { title = "ABC" })
Run Code Online (Sandbox Code Playgroud)

然后它被渲染(没有title属性):

<input class="text-box single-line" data-val="true" data-val-required="The User name field is required." id="UserName" name="UserName" type="text" value="" />
Run Code Online (Sandbox Code Playgroud)

总而言之,当我使用EditorFor时,title属性会丢失.

我知道TextBoxFor的第二个参数叫做htmlAttributes,而对于EditorFor来说它是additionalViewData,但是我已经看到了EditorFor可以渲染这个参数提供的属性的例子.

任何人都可以解释我做错了什么,以及如何在使用EditorFor时获得title属性?

Col*_*ern 14

我想我找到了一个更好的解决方案.EditorFor将additionalViewData作为参数.如果你给它一个带有属性的名为"htmlAttributes"的参数,那么我们可以用它做一些有趣的事情:

@Html.EditorFor(model => model.EmailAddress,
                new { htmlAttributes = new { @class = "span4",
                                             maxlength = 128,
                                             required = true,
                                             placeholder = "Email Address",
                                             title = "A valid email address is required (i.e. user@domain.com)" } })
Run Code Online (Sandbox Code Playgroud)

在模板中(在本例中为EmailAddress.cshtml),您可以提供一些默认属性:

@Html.TextBox("",
              ViewData.TemplateInfo.FormattedModelValue,
              Html.MergeHtmlAttributes(new { type = "email" }))
Run Code Online (Sandbox Code Playgroud)

魔术通过这个辅助方法汇集在一起​​:

public static IDictionary<string, object> MergeHtmlAttributes<TModel>(this HtmlHelper<TModel> htmlHelper, object htmlAttributes)
{
    var attributes = htmlHelper.ViewData.ContainsKey("htmlAttributes")
                            ? HtmlHelper.AnonymousObjectToHtmlAttributes(htmlHelper.ViewData["htmlAttributes"])
                            : new RouteValueDictionary();

    if (htmlAttributes != null)
    {
        foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(htmlAttributes))
        {
            var key = property.Name.Replace('_', '-');
            if (!attributes.ContainsKey(key))
            {
                attributes.Add(key, property.GetValue(htmlAttributes));
            }
        }
    }

    return attributes;
}
Run Code Online (Sandbox Code Playgroud)

当然,如果您正在使用原始HTML,您可以修改它以呈现属性:

public static MvcHtmlString RenderHtmlAttributes<TModel>(this HtmlHelper<TModel> htmlHelper, object htmlAttributes)
{
    var attributes = htmlHelper.ViewData.ContainsKey("htmlAttributes")
                            ? HtmlHelper.AnonymousObjectToHtmlAttributes(htmlHelper.ViewData["htmlAttributes"])
                            : new RouteValueDictionary();

    if (htmlAttributes != null)
    {
        foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(htmlAttributes))
        {
            var key = property.Name.Replace('_', '-');
            if (!attributes.ContainsKey(key))
            {
                attributes.Add(key, property.GetValue(htmlAttributes));
            }
        }
    }

    return MvcHtmlString.Create(String.Join(" ",
        attributes.Keys.Select(key =>
            String.Format("{0}=\"{1}\"", key, htmlHelper.Encode(attributes[key])))));
}
Run Code Online (Sandbox Code Playgroud)


lko*_*lko 12

在MVC3中,如果您创建自定义EditorFor模板,则可以使用此类解决方法添加标题(和其他htmlAttributes).这个案例是为值可选而编写的,editorFor调用不需要包含object additionalViewData

@Html.EditorFor(m => m.UserName, "CustomTemplate", new { title = "ABC" })
Run Code Online (Sandbox Code Playgroud)

EditorTemplates/CustomTemplate.cshtml

@{
    string s = "";
    if (ViewData["title"] != null) {
        // The ViewData["name"] is the name of the property in the addtionalViewData...
        s = ViewData["title"].ToString();
    }
}

@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { title = s })
Run Code Online (Sandbox Code Playgroud)

我做了类似于在EditorTemplate中包含可选类的东西.您可以根据需要向addtionalViewData添加任意数量的项目,但需要在EditorFor模板中处理每个项目.


Dar*_*rov 5

您可能需要看看下面的博客张贴这说明如何实现自定义的元数据提供者,以定义HTML属性,如您的视图模型使用数据标注class,maxlength,title,...这然后可以在配合使用模板化的助手.

  • 令人印象深刻的是,这个解决方案是核桃的众所周知的大锤.有更微妙的解决方案吗? (3认同)
  • 人们,投票谁同意这是一个无聊的限制.http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/3183610-allow-htmlattributes-in-asp-mvc-editorfor (2认同)