使用Html.RadioButtonFor和Html.LabelFor获取相同的Model但不同的值

Mar*_*arc 33 razor asp.net-mvc-3

我有这个剃刀模板

<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>
Run Code Online (Sandbox Code Playgroud)

这给了我这个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>
Run Code Online (Sandbox Code Playgroud)

所以我有Items_1__Value两次ID - 当然 - 不好,当我点击第二个标签"false"时,在浏览器中不起作用,第一个收音机将被激活.

我知道我可以在RadioButtonFor中添加一个自己的Id并用我的标签来引用它,但这不是很好,是吗?特别是因为我处于一个循环中而且不能只使用带有附加数字的名称"value",这最终会在我的最终HTML标记中出现在多个Dom Ids中.

不应该是一个很好的解决方案吗?

小智 58

不要过度设计解决方案.你要做的就是让单选按钮响应文本的点击.保持简单,只需将单选按钮包裹在标签标签中:

<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>
Run Code Online (Sandbox Code Playgroud)

LabelFor html帮助程序通常用于从View模型的Display属性中引入Name(例如"[Display(Name ="输入您的名字))]).

使用单选按钮时,名称并不是特别有用,因为每个单选按钮都有不同的文本行,这意味着您无论如何都难以将文本编码到视图中.

  • +1你的头上钉了一针:"不要过度设计解决方案." (4认同)
  • 对于那些想知道这是否是HTML中的良好实践并且没有任何其他副作用的人,请参阅http://stackoverflow.com/questions/774054/should-i-put-input-tag-inside-label-tag (4认同)

Sco*_*pey 47

我一直想知道MVC如何确定"嵌套"字段名称和ID.需要对MVC源代码进行一些研究才能弄清楚,但我认为我有一个很好的解决方案.

EditorTemplates和DisplayTemplates如何确定字段名称和ID

随着EditorTemplates和DisplayTemplates的引入,添加了MVC框架ViewData.TemplateInfo,其中包含当前的"字段前缀",例如"Items[1].".嵌套模板使用它来创建唯一的名称和ID.

创建我们自己的唯一ID:

TemplateInfo类包含一个有趣的方法,GetFullHtmlFieldId.我们可以使用它来创建我们自己的唯一ID,如下所示:

@{string id = ViewData.TemplateInfo.GetFullHtmlFieldId("fieldName");}
@* This will result in something like "Items_1__fieldName" *@
Run Code Online (Sandbox Code Playgroud)

为了胜利

以下是如何为您的示例实现正确的行为:

<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>
Run Code Online (Sandbox Code Playgroud)

这将为您提供以下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>
Run Code Online (Sandbox Code Playgroud)

放弃

我的Razor语法不发达,所以如果此代码有语法错误,请告诉我.

物有所值

非常不幸的是,这个功能并不是内置的RadioButtonFor.似乎合乎逻辑的是,所有渲染的单选按钮都应该具有一个ID,它是nameAND 的组合value,但事实并非如此 - 也许是因为这与所有其他Html助手不同.
为此功能创建自己的扩展方法似乎也是一种合理的选择.但是,使用"表达式语法"可能会变得棘手......所以我建议重载.RadioButton(name, value, ...)而不是RadioButtonFor(expression, ...).你也可能想要超载.Label(name, value).
我希望这一切都有意义,因为该段落中有很多"填空".

  • 是的,生成的属性的名称是小写的,但是我已经切换到`@ for`语法,因为它似乎是惯例.干杯 (4认同)

Ben*_*Ben 8

@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 })
Run Code Online (Sandbox Code Playgroud)

这允许您单击标签并按照您的预期选择相关的单选按钮.