Asp.net mvc 3 TextBoxFor vs EditorFor,htmlAttributes vs additionalViewData

Asp.net mvc 3 TextBoxFor vs EditorFor,htmlAttributes vs additionalViewData,asp.net-mvc-3,Asp.net Mvc 3,为了演示一个问题,我创建了一个默认的MVC3项目(使用razor) 在登录页面上,有一行: @Html.TextBoxFor(m => m.UserName) 如果我将此更改为: @Html.TextBoxFor(m => m.UserName, new { title = "ABC" }) 然后将其呈现为(具有标题属性): 然后它被渲染(没有标题属性)为: 总之,当我使用EditorFor时,title属性丢失了 我知道TextBoxFor的第二个参数称为htmlAttri

为了演示一个问题,我创建了一个默认的MVC3项目(使用razor)

在登录页面上,有一行:

@Html.TextBoxFor(m => m.UserName)
如果我将此更改为:

@Html.TextBoxFor(m => m.UserName, new { title = "ABC" })
然后将其呈现为(具有标题属性):

然后它被渲染(没有标题属性)为:


总之,当我使用EditorFor时,title属性丢失了

我知道TextBoxFor的第二个参数称为htmlAttributes,EditorFor的第二个参数是additionalViewData,但是我看到过EditorFor可以呈现随此参数提供的属性的示例


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

您可以看一下,它说明了如何在视图模型上实现自定义元数据提供程序和使用数据注释,以便定义html属性,例如
最大长度
标题
。。。然后,可以将其与模板化助手结合使用。

在MVC3中,如果为模板创建自定义编辑器,则可以使用这种解决方法添加标题(和其他htmlAttributes)。本例中的值是可选的,editorFor调用不需要包含
对象additionalViewData

@Html.EditorFor(m => m.UserName, "CustomTemplate", new { title = "ABC" })
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 })

我做了一些非常类似的事情,在EditorTemplate中包含一个可选类。您可以向AddationalViewData添加任意多个项目,但需要在EditorFor模板中处理每个项目。

我想我找到了一个更好的解决方案。EditorFor将附加ViewData作为参数。如果您给它一个名为“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)" } })
在模板(本例中为EmailAddress.cshtml)中,您可以提供一些默认属性:

@Html.TextBox("",
              ViewData.TemplateInfo.FormattedModelValue,
              Html.MergeHtmlAttributes(new { type = "email" }))
通过此帮助器方法,魔术得以实现:

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;
}
公共静态IDictionary MergeHtmlAttributes(此HtmlHelper HtmlHelper,对象htmlAttributes)
{
var attributes=htmlHelper.ViewData.ContainsKey(“htmlAttributes”)
?HtmlHelper.AnonymousObjectToHtmlAttributes(HtmlHelper.ViewData[“htmlAttributes”])
:新建RouteValueDictionary();
如果(htmlAttributes!=null)
{
foreach(TypeDescriptor.GetProperties(htmlAttributes)中的PropertyDescriptor属性)
{
var key=property.Name.Replace(“”、“-”);
如果(!attributes.ContainsKey(键))
{
Add(key,property.GetValue(htmlAttributes));
}
}
}
返回属性;
}
当然,如果您正在使用原始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])))));
}
public static MvcHtmlString renderhtmllattributes(此HtmlHelper HtmlHelper,对象htmlAttributes)
{
var attributes=htmlHelper.ViewData.ContainsKey(“htmlAttributes”)
?HtmlHelper.AnonymousObjectToHtmlAttributes(HtmlHelper.ViewData[“htmlAttributes”])
:新建RouteValueDictionary();
如果(htmlAttributes!=null)
{
foreach(TypeDescriptor.GetProperties(htmlAttributes)中的PropertyDescriptor属性)
{
var key=property.Name.Replace(“”、“-”);
如果(!attributes.ContainsKey(键))
{
Add(key,property.GetValue(htmlAttributes));
}
}
}
返回MvcHtmlString.Create(String.Join(“”),
attributes.Keys.Select(key=>
String.Format(“{0}=\”{1}\”,key,htmlHelper.Encode(attributes[key]щщ));
}

这个解决方案虽然令人印象深刻,但却是众所周知的核桃大锤。还有更微妙的解决办法吗?@G-unit,没有。EditorFor不支持传递html属性。这毫无意义,因为您甚至不知道该模板将如何实现。它可能是一个html属性没有意义的自定义模板。因此,实现这一点的唯一方法是编写自定义元数据提供程序。就我个人而言,这就是我所使用的,我对结果非常满意。谢谢你,我向你的智慧致敬!人们,投票赞成这是一个无聊的限制。太棒了,我正想问这个问题。请您提供一个完整的示例项目,使用您发布的代码,好吗?我是ASP.NET新手,不知道该将
mergeHtmlatAttributes
renderHtmlatAttributes
类放在何处。@RosdiKasim-这些是我通常存储在静态类中的扩展方法,这些静态类要么反映HTML帮助程序的公共集的命名空间,要么是我在视图的web.config中包含的新命名空间文件夹,这样我就不必在每页上不断引用它。所以基本上“HtmlHelperExtensions.cs”位于项目根目录或基础设施文件夹中。很好的模式!感谢分享:)您可以使用HtmlHelper.AnonymousObjectToHtmlatAttributes()方法改进此功能。
@Html.TextBox("",
              ViewData.TemplateInfo.FormattedModelValue,
              Html.MergeHtmlAttributes(new { type = "email" }))
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;
}
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])))));
}