好的,让我们做一些研究。首先,您不需要唯一的 id 来通过单击标签来切换复选框/收音机。其实你根本不需要身份证!您所要做的就是将您的输入包装在<label>
标签内:
<label>
<input type="radio" name="radio" value="1" /> Radio 1
</label>
到目前为止一切顺利,ASP.NET MVC 为您提供了编写自己的 html 助手的能力,让我们为Enum
模型字段编写一个!
想象一下,我们有一些注册模型:
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
该死!我刚刚复制粘贴了教程模型o_O。我们现在想要的是获取用户的性别,所以我们添加了一个Gender
枚举:
public enum Gender
{
Iamparanoic = 0,
Male = 1,
Female = 2,
}
并将类型Gender
字段添加Gender
到我们的模型中(希望 C# 有一个Gender
访问修饰符!)
public Gender Gender { get; set; }
现在,是时候使用一些 asp.net 魔法并编写我们的 html 助手了:
public static MvcHtmlString RadioButtonsListForEnum<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
{
var sb = new StringBuilder();
sb.Append("<ul>"); //we want it to look cool, dont' we?
foreach (var value in Enum.GetValues(typeof(TEnum)))
{
var radio = htmlHelper.RadioButtonFor(expression, value).ToHtmlString(); //you can generage any id and pass it to helper, or use a tagbuilder
sb.AppendFormat(
"<li><label>{0} {1}</label></li>",
radio,
((Enum)value).GetEnumName() //instead of it you can grab e.g. Display/Description attribute value or w/e else
);
}
sb.Append("</ul");
return MvcHtmlString.Create(sb.ToString());
}
它的用法如下所示:
@Html.RadioButtonsListForEnum(m => m.Gender)
太漂亮了,不是吗?当然你可以添加很多自定义,比如渲染具有唯一 mvc 样式 id 的单选按钮,各种 html 属性等,但这只是一个示例,正确的方式。
接下来,我们还要渲染复选框列表!
public static MvcHtmlString CheckBoxListForEnum<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, IDictionary<string, object> htmlAttributes = null)
{
var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
var enumValue = Convert.ToInt32(metadata.Model);
var sb = new StringBuilder();
foreach (var value in Enum.GetValues(typeof (TEnum)))
{
var val = Convert.ToInt32(value);
var checkbox = new TagBuilder("input");
checkbox.MergeAttribute("type", "checkbox");
checkbox.MergeAttribute("value", value.ToString());
checkbox.MergeAttribute("name", htmlHelper.NameFor(expression).ToString());
if ((enumValue & val) == val)
checkbox.MergeAttribute("checked", "checked");
if (htmlAttributes != null)
checkbox.MergeAttributes(htmlAttributes);
var label = new TagBuilder("label") { InnerHtml = checkbox + ((Enum)value).GetEnumName() };
sb.Append(label);
sb.Append("<br/>");
}
return new MvcHtmlString(sb.ToString());
}
再次,简单的用法:
@Html.CheckBoxListForEnum(m => m.Gender)
顺便说一句,它仅适用于标有Flags
属性的枚举,当然你会遇到模型绑定的问题 - 它需要自定义绑定器。但这是另一个问题,我希望Jon Skeet可以回答:)