使用以下代码时,字段的id和标签的for属性中的id不相同。LabelFor和TextBoxFor不生成相同的ID
<%: Html.LabelFor(x => x.Localizations["en"]) %> => Localizations[en]
<%: Html.TextBoxFor(x=> x.Localizations["en"]) %> => Localizations_en_
<%: Html.LabelFor(x => x.Localizations["en"].Property) %>
=> Localizations[en]_Property
<%: Html.TextBoxFor(x=> x.Localizations["en"].Property) %>
=> Localizations_en__Property
我追溯反射器中的代码,并看到值的生成方式不同。不使用相同的辅助方法。
LabelFor使用HtmlHelper.GenerateIdFromName
和TextBoxFor使用TagBuilder#GenerateId
。
有没有人知道这个原因或解决方法(除了编写自己的整套输入/ textarea/select助手)?或者它是一个错误?
UPDATE:
因为我无论如何使用标签中的HTML辅助与标签文本第二个参数,我没有修改它使用相同ID生成代码的表单字段帮手。
public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, string labelText)
{
// The main part of this code is taken from the internal code for Html.LabelFor<TModel, TValue>(...).
var metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
var fieldName = ExpressionHelper.GetExpressionText(expression);
TagBuilder builder = new TagBuilder("label");
// Generate the id as for the form fields (adds it to self).
builder.GenerateId(fieldName);
// Use the generated id for the 'for' attribute.
builder.Attributes.Add("for", builder.Attributes["id"]);
// Remove the id again.
builder.Attributes.Remove("id");
builder.SetInnerText(labelText);
return MvcHtmlString.Create(builder.ToString());
}
这解决了我的眼前问题,但它并没有回答这个问题,为什么执行看起来像它在MVC2一样。如果有原因的话。顺便说一句:没有必要实际修改HTML5中的id/for属性,因为如果你愿意,有一个看起来像^~[]
的ID是完全合法的。所有主流浏览器都支持它。这很好地由Mathias Bynens解释。
更新2:
这并不是解决问题的全部实际,因为DefaultModelBinder不能绑定到也无妨。使用字典中嵌套的对象似乎并不在MVC 2的字段名称生成的支持,因为它产生:
<input type="text" name="Dict[en]" value="(VALUE)">
而不是什么模型绑定想:
<input type="hidden" name="Dict[0].Key" value="en">
<input type="text" name="Dict[0].Value" value="(VALUE)">
奇怪的是,它这种方式从盒子里出来。
我试着为它创建一个自定义的模型绑定,但我不能让MVC2使用它无论我尝试使用它:
ModelBinders.Binders.Add(typeof(IDictionary<string,object>), new DictionaryModelBinder());
ModelBinders.Binders.Add(typeof(IDictionary<string,string>), new DictionaryModelBinder());
ModelBinders.Binders.Add(typeof(IDictionary), new DictionaryModelBinder());
ModelBinders.Binders.Add(typeof(Dictionary), new DictionaryModelBinder());
所以现在它看起来像它的回用隐藏的.Key
字段手动创建名称属性值。
我注意到了。尽管我从不在重复结构中使用标签。我用一张桌子。 你试过在foreach循环中吗?这看起来如何? – Stefanvds 2010-08-18 08:53:00
我实际上在foreach循环中使用它,这是一个简单的例子,带有明确的可读性键。 – 2010-08-18 08:56:36