1

In certain cases I want to display SelectList object not using DropDownListFor helper. Instead, I want to create a helper that iterates over the SelectListItems, and draw something different.

I have created an 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>

The RadioButtonOptions class is a ViewModel:

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

The final resul looks like this:

enter image description here

My ViewModel is like this (simplified):

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

    public RadioButtonOptions VisitOptions { get; set; }
}

And I use it in Razor View as:

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

The problem I have is that I want this to work more like the DropDownListFor, so the lamda expresion I pass is the property holding the selected value, and then just pass the SelectList object (or a custom list).

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

So, I think doing this using EditorTemplates will not be possible. Any idea in how to accomplish this?

2
  • It is possible - by passing the list as additionalViewData and the getting it in the template using (say) var List = ViewData["...."];, but a HtmlHelper extension method would be better. Commented Apr 30, 2017 at 21:49
  • @StephenMuecke I will try the HtmlHelper extension method... thanks! Commented Apr 30, 2017 at 22:31

1 Answer 1

1

Thanks to @StephenMuecke suggestion, I ended up with this HtmlHelper extension method:

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

Not particulary proud of my htmlFieldName.Replace(".","_"), but works.

Sign up to request clarification or add additional context in comments.

2 Comments

Note that HtmlHelper already contains a static method GenerateIdFromName(string name) but you could also generate the html as <label><input type="radio" ...... /><span>yourText</span></label> and use var radio = htmlHelper.RadioButtonFor(expression, item.Value, new { id = "" }) to remove the id unless you specifically need to for a css or javascript selector
Yeap, the id the radiobutton must match the FOR attribute in the label, in order to have the intended behavior. May be changing the markup as you pointed has the same final result. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.