Search code examples
c#asp.net-mvclambdahtml-helperexpression-trees

How to create a custom HTML Helper method DropDownFor in ASP.Net MVC


I'm trying to create a dropdown box that will render a label under certain conditions when teh user does not have access to it.

so far I have come up with this

public static MvcHtmlString ReadOnlyCapableDropDownFor<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression, 
        IEnumerable<SelectListItem> selectList, 
        bool enabled, 
        object htmlAttributes
)
{
     return !enabled ? htmlHelper.DisplayFor(expression)
          : htmlHelper.DropDownListFor(expression, selectList, htmlAttributes);
}

This correctly renders a label when enabled is false and a dropdown when it is true, the issue is that the text of the label is the id of the selected select list value rather than the text that would normally show in in the dropdown.

This makes sense as I'm using the expression for the value of the display for, how do I use this expression to get the select list item text value rather than the data value?


Solution

  • You could compile the expression and retrieve the value from the model. Then, choose the correct text from the selectList.

    TProperty val = expression.Compile().Invoke(htmlHelper.ViewData.Model);
    SelectListItem selectedItem = selectList.Where(item => item.Value == Convert.ToString(val)).FirstOrDefault();
    string text = "";
    if (selectedItem != null) text = selectedItem.Text;
    
    return !enabled ? new MvcHtmlString("<span>" + text + "</span>")
          : htmlHelper.DropDownListFor(expression, selectList, htmlAttributes);
    

    I think returning an ad-hoc MvcHtmlString should suffice in this case, since all the info you have is contained in that selectList string anyway. (It's not like your helper method has access to any data annotations, etc.)