Tom
Tom

Reputation: 2230

Show list of all Enums of type<T> except the one passed via lambda

In my MVC application, I've created a helper which should take an enum from the model and then display radio buttons for all of the other available enums of that type.

For example, you have the enum Satus which has Active, Inactive, Closed and the model for the page has Status = Status.Active so you want to display radio buttons for Inactive and Closed.

Going forward with this example, the MVC view calls helper RadioButtonForEnum:

@Html.RadioButtonForEnum(model => model.Status)

RadioButtonForEnum then gets the list of all Enums of that type and prints them out as radio buttons; however, I'm not sure how to get to the enum that was passed to exclude it from names

public static MvcHtmlString RadioButtonForEnum<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
{
    var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
    var names = Enum.GetNames(metaData.ModelType);
    var sb = new StringBuilder();
    foreach (var name in names)
    {
        var id = string.Format(
            "{0}_{1}_{2}",
            htmlHelper.ViewData.TemplateInfo.HtmlFieldPrefix,
            metaData.PropertyName,
            name
        );

        var radio = htmlHelper.RadioButtonFor(expression, name, new { id = id }).ToHtmlString();
        sb.AppendFormat("<label for=\"{1}\">{0}{2}</label>", radio, id, HttpUtility.HtmlEncode(StringHelpers.PascalCaseToSpaces(name)));
    }

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

Upvotes: 0

Views: 443

Answers (4)

Mister Epic
Mister Epic

Reputation: 16723

Completely untested here as I don't have my own computer, but what about changing your signature to:

public static MvcHtmlString RadioButtonForEnum<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, Enum Status)

This will allow you to pass in the Status enum and interrogate its value:

public static MvcHtmlString RadioButtonForEnum<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, Enum Status){
        var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        var names = Enum.GetNames(metaData.ModelType);
        var sb = new StringBuilder();
        foreach (var name in names)
        {
            if (!name.Equals(Status.ToString()){
            var id = string.Format(
                "{0}_{1}_{2}",
                htmlHelper.ViewData.TemplateInfo.HtmlFieldPrefix,
                metaData.PropertyName,
                name
        );

        var radio = htmlHelper.RadioButtonFor(expression, name, new { id = id }).ToHtmlString();
        sb.AppendFormat("<label for=\"{1}\">{0}{2}</label>", radio, id, HttpUtility.HtmlEncode(StringHelpers.PascalCaseToSpaces(name)));
        }
}

And you would call it from your view like this:

@Html.RadioButtonForEnum(model => model.Status, Model.Status)

Upvotes: 0

Trevor Elliott
Trevor Elliott

Reputation: 11252

Quick and dirty way:

foreach (var name in names)
{
    if (name == metaData.Model.ToString())
        continue;

    ...
}

Upvotes: 0

Boris B.
Boris B.

Reputation: 5024

Something like

var modelValue = expression.Compile()(htmlHelper.ViewData.Model);
...
foreach (var name in names.Where(s => s != modelValue.ToString())
...

You need the model instance to get the current enum value to avoid, you could get to it inside the HtmlHelper by using HtmlHelper.ViewData.Model as above.

Upvotes: 1

Tim S.
Tim S.

Reputation: 56536

I don't think you have the model object, as-is. You could add it as another parameter:

@Html.RadioButtonForEnum(Model, model => model.Status)

public static MvcHtmlString RadioButtonForEnum<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, TModel model, Expression<Func<TModel, TProperty>> expression)
{
    string currentStatusName = expression.Compile()(model).ToString();
    ...

Upvotes: 1

Related Questions