Asp.net mvc 3 对同一模型但不同的值使用Html.radioButtonOn和Html.LabelFor
我有这个剃须刀模板Asp.net mvc 3 对同一模型但不同的值使用Html.radioButtonOn和Html.LabelFor,asp.net-mvc-3,razor,Asp.net Mvc 3,Razor,我有这个剃须刀模板 <table> <tr> <td>@Html.RadioButtonFor(i => i.Value, "1")</td> <td>@Html.LabelFor(i => i.Value, "true")</td> </tr> <tr> <td>@Html.RadioButtonFor(i => i.Value, "0")<
<table>
<tr>
<td>@Html.RadioButtonFor(i => i.Value, "1")</td>
<td>@Html.LabelFor(i => i.Value, "true")</td>
</tr>
<tr>
<td>@Html.RadioButtonFor(i => i.Value, "0")</td>
<td>@Html.LabelFor(i => i.Value, "false")</td>
</tr>
</table>
@RadioButton(i=>i.Value,“1”)
@LabelFor(i=>i.Value,“true”)
@RadioButton(i=>i.Value,“0”)
@LabelFor(i=>i.Value,“false”)
这给了我这个HTML
<table>
<tr>
<td><input id="Items_1__Value" name="Items[1].Value" type="radio" value="1" /></td>
<td><label for="Items_1__Value">true</label></td>
</tr>
<tr>
<td><input checked="checked" id="Items_1__Value" name="Items[1].Value" type="radio" value="0" /></td>
<td><label for="Items_1__Value">false</label></td>
</tr>
</table>
真的
假的
因此,我有两次IDItems_1__值
,这当然是不好的,当我点击第二个标签“false”时,在浏览器中无法工作,第一个收音机将被激活
我知道我可以在RadioButton上添加一个自己的Id,并将其与我的标签一起引用,但这不是很好,是吗?特别是因为我处于一个循环中,不能只使用名称“value”加上一个数字,这也会在最终的HTML标记中出现多个Dom ID
这不是个好办法吗?显然有个好办法
<td>@Html.RadioButtonFor(i => i.Value, true)</td>
<td>@Html.RadioButtonFor(i => i.Value, false)</td>
@Html.radiobutton(i=>i.Value,true)
@RadioButton(i=>i.Value,false)
虽然不完美,但很管用
<table>
<tr>
<td>@ReplaceName(Html.RadioButtonFor(i => i.Value, "1"))</td>
<td>@Html.LabelFor(i => i.Value[0], "true")</td>
</tr>
<tr>
<td>@ReplaceName(Html.RadioButtonFor(i => i.Value, "0"))</td>
<td>@Html.LabelFor(i => i.Value[1], "false")</td>
</tr>
</table>
@functions {
int counter = 0;
MvcHtmlString ReplaceName(MvcHtmlString html){
return MvcHtmlString.Create(html.ToString().Replace("__Value", "__Value_" + counter++ +"_"));
}
}
@ReplaceName(Html.radioButton(i=>i.Value,“1”))
@LabelFor(i=>i.Value[0],“true”)
@ReplaceName(Html.radioButton(i=>i.Value,“0”))
@LabelFor(i=>i.Value[1],“false”)
@功能{
int计数器=0;
MvcHtmlString替换名称(MvcHtmlString html){
返回MvcHtmlString.Create(html.ToString().Replace(“\uuuuu Value”,“\uuuuu Value”+计数器+++“);
}
}
我一直想知道MVC是如何确定“嵌套”字段名和ID的。需要对MVC源代码进行一些研究才能找到答案,但我认为我有一个很好的解决方案
EditorTemplates和DisplayTemplates如何确定字段名和ID
随着EditorTemplates和DisplayTemplates的引入,MVC框架添加了ViewData.TemplateInfo
,其中包含当前的“字段前缀”,例如“Items[1]”。
。嵌套模板使用它来创建唯一的名称和ID
创建我们自己的唯一ID:
该类包含一个有趣的方法。我们可以使用它创建自己的唯一ID,如下所示:
@{string id = ViewData.TemplateInfo.GetFullHtmlFieldId("fieldName");}
@* This will result in something like "Items_1__fieldName" *@
为了胜利
以下是如何为您的示例实现正确的行为:
<table>
<tr>
@{string id = ViewData.TemplateInfo.GetFullHtmlFieldId("radioTrue");}
<td>@Html.RadioButtonFor(i => i.Value, "1", new{id})</td>
<td>@Html.LabelFor(i => i.Value, "true", new{@for=id})</td>
</tr>
<tr>
@{id = ViewData.TemplateInfo.GetFullHtmlFieldId("radioFalse");}
<td>@Html.RadioButtonFor(i => i.Value, "0", new{id})</td>
<td>@Html.LabelFor(i => i.Value, "false", new{@for=id})</td>
</tr>
</table>
@{string id=ViewData.TemplateInfo.GetFullHtmlFieldId(“radioTrue”);}
@RadioButton(i=>i.Value,“1”,新的{id})
@LabelFor(i=>i.Value,“true”,新的{@for=id})
@{id=ViewData.TemplateInfo.GetFullHtmlFieldId(“radioFalse”);}
@RadioButton(i=>i.Value,“0”,新的{id})
@LabelFor(i=>i.Value,“false”,新的{@for=id})
这将为您提供以下HTML:
<table>
<tr>
<td><input id="Items_1__radioTrue" name="Items[1].Value" type="radio" value="1" /></td>
<td><label for="Items_1__radioTrue">true</label></td>
</tr>
<tr>
<td><input checked="checked" id="Items_1__radioFalse" name="Items[1].Value" type="radio" value="0" /></td>
<td><label for="Items_1__radioFalse">false</label></td>
</tr>
</table>
真的
假的
免责声明
我的Razor语法还不完善,所以请让我知道这段代码是否有语法错误
为了它的价值
非常不幸的是,RadioButtonFor
没有内置此功能。所有呈现的单选按钮都应该有一个ID,该ID是其名称
和值
的组合,这似乎是合乎逻辑的,但事实并非如此——可能是因为这与所有其他Html帮助程序不同。为这个功能创建自己的扩展方法似乎也是一个合乎逻辑的选择。然而,使用“表达式语法”可能会变得棘手。。。因此,我建议重载
.RadioButton(名称、值等)
而不是RadioButton(表达式等)
。您可能还需要.Label(名称、值)
的重载。我希望这一切都是有意义的,因为那一段中有很多“填空”。@Scott Rippey几乎做到了,但我猜他对我一定使用了不同版本的MVC3,因为对我来说
@Html.LabelFor
没有需要3个参数的重载。我发现使用普通的@Html.Label
效果很好:
@{string id = ViewData.TemplateInfo.GetFullHtmlFieldId("radioButton_True");}
@Html.Label(id, "True:")
@Html.RadioButtonFor(m => m.radioButton, true, new { id })
@{id = ViewData.TemplateInfo.GetFullHtmlFieldId("radioButton_False");}
@Html.Label(id, "False:")
@Html.RadioButtonFor(m => m.radioButton, false, new { id })
这使您可以按预期单击标签并选择相关的单选按钮。不要过度设计解决方案。你所要做的就是让单选按钮对文本的点击做出反应。保持简单,只需将单选按钮包装在标签标签中:
<table>
<tr>
<td><label>@Html.RadioButtonFor(i => i.Value, "1")True</label></td>
</tr>
<tr>
<td><label>@Html.RadioButtonFor(i => i.Value, "0")False</label></td>
</tr>
</table>
@RadioButton(i=>i.Value,“1”)True
@RadioButton(i=>i.Value,“0”)False
LabelFor html helper通常用于从视图模型上的“显示”属性引入名称(例如“[Display(Name=“Enter your Name”)]”)
对于单选按钮,名称并不是特别有用,因为每个单选按钮都有一行不同的文本,这意味着您始终无法将文本硬编码到视图中。这是一个可以使用的HtmlHelper,尽管您可能需要自定义它。只经过了少量测试,所以YMMV
public static MvcHtmlString RadioButtonWithLabelFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, object value, object htmlAttributes = null)
{
var name = ExpressionHelper.GetExpressionText(expression);
var id = helper.ViewData.TemplateInfo.GetFullHtmlFieldId(name + "_" + value);
var viewData = new ViewDataDictionary(helper.ViewData) {{"id", id}};
if (htmlAttributes != null)
{
var viewDataDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
foreach (var keyValuePair in viewDataDictionary)
{
viewData[keyValuePair.Key] = keyValuePair.Value;
}
}
var radioButton = helper.RadioButtonFor(expression, value, viewData);
var tagBuilder = new TagBuilder("label");
tagBuilder.MergeAttribute("for", id);
tagBuilder.InnerHtml = value.ToString();
return new MvcHtmlString(radioButton.ToHtmlString() + tagBuilder.ToString());
}
public static MvcHtmlString RadioButtonWithLabelFor(此HtmlHelper帮助程序、表达式、对象值、对象htmlAttributes=null)
{
var name=ExpressionHelper.GetExpressionText(表达式);
var id=helper.ViewData.TemplateInfo.getFullHtmlFieldDid(name+“\u”+值);
var viewData=newviewdatadictionary(helper.viewData){{{“id”,id};
如果(htmlAttributes!=null)
{
var viewDataDictionary=HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
foreach(viewDataDictionary中的var keyValuePair)
{
viewData[keyValuePair.Key]=keyValuePair.Value;
}
}
var radioButton=helper.radioButton(表达式、值、视图数据);
var tagBuilder=新的tagBuilder(“标签”);
tagBuilder.MergeAttribute(“for”,id);
tagBuilder.InnerHtml=value.ToString();
返回新的MvcHtmlString(radioButton.ToHtmlString()+tagBuilder.ToString());
}
您可以添加带有标记的文本
<td>@Html.RadioButtonFor(i => i.Value, true) <text>True</text></td>
<td>@Html.RadioButtonFor(i => i.Value, false) <text>False</text></td>
@Html.radiobutton(i=>i.Value,true)true
@RadioButton(i=>i.Value,false)false
很抱歉,但这不是一个好的解决方案-使用该代码