Создайте помощник ASP.NET MVC Html, аналогичный DropDownListFor

В некоторых случаях я хочу отображать объект SelectList без использования помощника DropDownListFor. Вместо этого я хочу создать помощник, который выполняет итерацию по элементам SelectListItems и рисует что-то другое.

Я создал EditorTemplate:

@model RadioButtonOptions

<div class=" switch-field noselect" style="padding-left: 0px;">
    @foreach (SelectListItem op in Model.Values.Items)
    {
        var idLabelF = ViewData.TemplateInfo.GetFullHtmlFieldId("") + "_" + op.Value;
        var esChecked = "";

        if (op.Selected)
        {
            esChecked = "checked";
        }

        <input type="radio" id="@idLabelF" name="@(ViewData.TemplateInfo.GetFullHtmlFieldName(""))" value="@op.Value" @esChecked />
        <label for="@idLabelF" style="width: 100px;">@op.Text</label>

    }
</div>

Класс RadioButtonOptions - это ViewModel:

public class RadioButtonOptions
    {
        public SelectList Values { get; set; }
    }

Окончательный результат выглядит следующим образом:

введите описание изображения здесь

Моя модель просмотра выглядит так (упрощенно):

public class MainVisitVM
{
    public MainVisit Visit { get; set; }

    public RadioButtonOptions VisitOptions { get; set; }
}

И я использую его в Razor View как:

    <div class="clearfix">
        @Html.LabelFor(x=> x.Visit.Tipo)
        <div class="input">
            @Html.EditorFor(x=> x.VisitOptions ) //HERE
        </div>
    </div>

У меня проблема в том, что я хочу, чтобы это работало больше как DropDownListFor, поэтому передаваемое мной выражение lamda - это свойство, содержащее выбранное значение, а затем просто передайте объект SelectList (или настраиваемый список).

<div class="clearfix">
    @Html.LabelFor(x=> x.Visit.Tipo)
    <div class="input">
         @Html.CustomDropDownListFor(x=> x.Visit.Tipo, Model.VisitOptions ) //This would be ideal!!
    </div>
</div>

Поэтому я думаю, что сделать это с помощью EditorTemplates будет невозможно. Есть идеи, как это сделать?


person Romias    schedule 30.04.2017    source источник
comment
Это возможно - путем передачи списка как additionalViewData и получения его в шаблоне с помощью (скажем) var List = ViewData["...."];, но метод расширения HtmlHelper будет лучше.   -  person    schedule 01.05.2017
comment
@StephenMuecke Я попробую метод расширения HtmlHelper ... спасибо!   -  person Romias    schedule 01.05.2017


Ответы (1)


Благодаря предложению @ StephenMuecke я остановился на этом HtmlHelper методе расширения:

public static MvcHtmlString RadioButtonForSelectList<TModel, TProperty>(
           this HtmlHelper<TModel> htmlHelper,
           Expression<Func<TModel, TProperty>> expression,
           SelectList listOfValues)
        {

            string htmlFieldName = ExpressionHelper.GetExpressionText(expression);

            if (listOfValues == null) return MvcHtmlString.Create(string.Empty);

            var wrapperDiv = new TagBuilder("div");
            wrapperDiv.AddCssClass("switch-field noselect");
            wrapperDiv.Attributes.Add("style", "padding-left: 0px;");

            var sb = new StringBuilder();

            foreach (SelectListItem item in listOfValues)
            {
                var idLabelF = htmlFieldName.Replace(".","_") + "_" + item.Value;

                var label = htmlHelper.Label(idLabelF, item.Text, new { style = "width: 100px;" }).ToHtmlString();
                var radio = htmlHelper.RadioButtonFor(expression, item.Value, new { id = idLabelF }).ToHtmlString();

                sb.AppendFormat("{0}{1}", radio, label);
            }

            wrapperDiv.InnerHtml = sb.ToString();

            return MvcHtmlString.Create(wrapperDiv.ToString());
        } 

Не особо горжусь своей htmlFieldName.Replace(".","_"), но работает.

person Romias    schedule 30.04.2017
comment
Обратите внимание, что HtmlHelper уже содержит статический метод GenerateIdFromName(string name), но вы также можете сгенерировать html как <label><input type="radio" ...... /><span>yourText</span></label> и использовать var radio = htmlHelper.RadioButtonFor(expression, item.Value, new { id = "" }) для удаления id, если вам не требуется специально для селектора css или javascript - person ; 01.05.2017
comment
Да, идентификатор радиокнопки должен соответствовать атрибуту FOR в метке, чтобы иметь предполагаемое поведение. Возможно, изменение разметки, как вы указали, даст тот же окончательный результат. Спасибо! - person Romias; 01.05.2017