Подтвердить что ты не робот

Правильный способ кодирования группы радиоустройств с помощью RadioButtonFor

Основываясь на моих исследованиях, правильный способ закодировать флажок в MVC выглядит следующим образом.

@Html.CheckBoxFor(m => m.RememberMe)
@Html.LabelFor(m => m.RememberMe)

Это сделает флажок, выведет метку для флажка и сделаем метку нажатой, что означает, что щелчок по метке также переключает флажок.

Но как насчет случая, когда есть несколько флажков для одного поля модели представления? (Например, возможно, каждый флажок представляет бит в целочисленном значении.) Или, что еще лучше, что делать с переключателями, где всегда есть несколько параметров, связанных с одним и тем же полем?

В этих случаях, похоже, проблемы с кодом выше. Либо не все элементы будут связаны с одним и тем же полем, либо будут отображены несколько элементов с одним и тем же идентификатором.

Я изучаю это некоторое время. Я нашел много решений; однако все они либо не имеют интерактивной метки, либо требуют кучу пользовательского и/или нестандартного кодирования. Некоторые избегают использования RadioButtonFor/LabelFor полностью, выбирая вместо этого код необработанного HTML.

Кодирование необработанного HTML в порядке, но разве дизайнеры MVC не ожидали, что нам может понадобиться несколько переключателей для одного и того же поля? И, если бы они это сделали, как они намеревались его кодировать?

EDIT:

После изучения этого еще один код, приведенный ниже, является лучшим способом, который я нашел, чтобы закодировать радиокнопки. Этот код предполагает, что я определил перечисление для каждого из моих параметров радио.

@Html.RadioButtonFor(m => m.Gender, Gender.Male, new { id = "gender-male" })
@Html.LabelFor(m => m.Gender, Gender.Male.ToString(), new { @for = "gender-male" })
@Html.RadioButtonFor(m => m.Gender, Gender.Female, new { id = "gender-female" })
@Html.LabelFor(m => m.Gender, Gender.Female.ToString(), new { @for = "gender-female" })

Возможно, это лучшее, что я могу ожидать, но это все еще немного беспокоит меня.

  • Почему так много настроек для базовых вещей, таких как идентификаторы? Опять же, разве Microsoft не ожидала, что нам нужно несколько переключателей, связанных с одним и тем же полем?

  • Если имя переименования не совпадает с описанием, которое я хочу для метки радиокнопки, этот подход, похоже, не поддерживает атрибуты поля, такие как [Display(Name = "")].

(Я думаю, правильная обработка нескольких флажков будет отложена на другой вопрос.)

4b9b3361

Ответ 1

Хорошо, сделаем некоторые исследования. Прежде всего, вам не нужен уникальный идентификатор для переключения флажка/радио, щелкнув метку. На самом деле вам вообще не нужен идентификатор! Все, что вам нужно сделать, это обернуть ваш вход в тег <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 к нашей модели (желание, С# имеет модификатор доступа 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-стиля, все виды атрибутов html и т.д., Но это всего лишь образец, ударный удар на правильный путь.

Далее, мы также хотим отобразить 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());
}

И снова простое использование:

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

Btw, он имеет значение только для перечислений, помеченных атрибутом Flags, и, конечно, у вас возникнут проблемы с привязкой к модели - для этого требуется специальное связующее. Но это еще один вопрос, и я надеюсь, что Jon Skeet может ответить на него:)

Ответ 2

На мой взгляд, я считаю, что ничего не делать с стороны Microsoft, чтобы справиться с тем случаем, о котором вы говорите.

начиная с Html-кода, как в html будут представлены несколько радио-кнопок?

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

выше - образец, который я привел из W3cSchools,

если вы хотите переключить переключатель, щелкнув метку, это можно сделать двумя способами в html

Первый способ - использовать тег for в метке

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

второй способ - поместить радиовход внутри тега метки

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

как вы можете видеть, его сочетание тегов, чтобы переключить переключатель, когда вы нажимаете на ярлык, Microsoft, я думаю, оставил его простым и гибким для разработчика, чтобы выбрать, что делать и как ему это нравится.

теперь, чтобы получить тот же результат в Mvc, либо вы производите код каждого переключателя, который у вас есть в одном из этих двух методов, упомянутых выше, либо чтобы сделать его более легким, напишите собственное расширение Mvc Html, и я рекомендую второй метод.

надеюсь, что это поможет вам