Correct Way to Code a Group of Radio Buttons using RadioButtonFor

Deadly 提交于 2019-12-05 01:06:00
Sergio

Ok, let's do some research. First of all, you don't need unique id to toggle checkbox/radio by clicking a label. Actually you don't need id at all! All you have to do is wrap your input inside <label> tag:

<label>
    <input type="radio" name="radio" value="1" /> Radio 1   
</label>

So far so good, ASP.NET MVC provides you ability to code your own html helpers, let's write one for Enum model field!

Imagine, we've got some registration model:

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; } 
}

Damn! I've just copy-pasted tutorial model o_O. What we want now - is to get user's gender, so we add a Gender enum:

public enum Gender
{
    Iamparanoic = 0,

    Male = 1,

    Female = 2,
}

and add Gender field of Gender type to our model (wish, c# had a Gender access modifier!)

public Gender Gender { get; set; }

Now, time to use some asp.net magic and write our html helper:

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());
}

and usage of that will look like:

@Html.RadioButtonsListForEnum(m => m.Gender)

So pretty, isn't it? Of course you can add hella lot's of customization, like rendering radiobuttons with unique mvc-style id's, all kindes of html attributes etc. but this is just a sample, ass kick to right way.

Next, we also want to render checkboxlist!

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());
}

And again, simple usage:

@Html.CheckBoxListForEnum(m => m.Gender)

Btw, it makes sence just for enums marked with Flags attribute, and of course you'll have troubles with model binding - it requires custom binder. But it's another question, and i hope Jon Skeet can answer it :)

In my opinion, i believe nothing to be done from Microsoft side to handle the case you are talking about.

starting from the Html code, how in html, the multi radio buttons will be presented?

<form action="">
<input type="radio" name="sex" value="male">Male<br>
<input type="radio" name="sex" value="female">Female
</form>

above is a sample I brought it from W3cSchools,

if you want to toggle the radio button by clicking the label, this can be done in two ways in html

first way is to use the for tag in the label

<input type="radio" id="myId" name="MyName" value="MyValue" />
<label for="myId">Display Name</label>

second way is to put the radio input inside a label tag

<label>
   <input type="radio" id="myId" name="MyName" value="MyValue"/> 
   Display Name
</label>

as you can see, its combination of tags to get the radio button toggles when you click on the label, Microsoft i think kept it simple and flexible to the developer to choose what to do and in the way he likes it.

now, to get the same result in Mvc, either you hard code each radio button you have in one of these 2 methods mentioned above, or to make it more easy, write your own Mvc Html extension, and I recommend the second method.

hope this will help you

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!