3

I started doing this to display some checkboxes in my view:

@Html.LabelFor(m => m.MyEnum, T("Pick Your Poison"))
<div>                
    @for(int i = 0; i < Model.Alcohol.Count; i++)
    {
        <label>
            @T(Model.Alcohol[i].Text)
            @Html.CheckBoxFor(m => Model.Alcohol[i].Selected)
            @Html.HiddenFor(m => Model.Alcohol[i].Value)
        </label>
    }
</div>

PLEASE NOTE: The important thing here is the @T method, which is used to handle translations of the text into other languages.

This works. I've got a simple enum, and some methods in the back end that turn it into text in the view. So, an enum such as:

public enum MyEnum
{
    Beer = 1,
    Vodka = 2,
    Rum = 3
}

will display list of checkboxes with those 3 choices. In my ViewModel I do this:

Alcohol= Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().Select(x =>
{
    return new SelectListItem { 
        Text = x.ToString().ToUpper(), Value = ((int)x).ToString()
        };
    }).ToList();
}

However, I want to have more descriptive text to accompany the checkbox. I would rather the enum have this or some similar type of system (I will explain the underscore):

public enum MyEnum
{
    I_like_Beer = 1,
    I_hate_Vodka = 2,
    Meh__Rum = 3
}

I was trying to create a method to strip out the underscore and replace it with a space, and in the case of the double underscore replace it with a comma, so when the checkboxes displayed they would look like:

I like Beer

I hate Vodka

Meh, Rum

But I don't know how to. Also, I am not sure this would be the best thing to do. I would love to preserve the @T function because then I can easily translate things in my app. Otherwise, doing anything else will sort of kill that for me.

Any examples of what I might should be doing? Thanks.

1 Answer 1

5

I like using data annotations for this kind of thing. This prevents the craziness with trying to figure out a variable-to-readable text convention.

public enum MyEnum
{
    [Description("I like beer")]
    Beer = 1,
    [Description("I hate vodka")]
    Vodka = 2,
    [Description("Meh, rum")]
    Rum = 3
};

You can access the value at runtime using reflection:

MyEnum sampleEnum = MyEnum.Beer;
var attr = typeof(MyEnum)
    .GetMember(sampleEnum.ToString())
    .First()
    .GetCustomAttributes(typeof(DescriptionAttribute), false)
    .First() as DescriptionAttribute;
string description = attr.Description;

Of course, that's a bit verbose (and still needs error handling), but you can create an extension method to simplify the usage syntax:

public static string GetDescriptionOrDefault<T>(this T enumValue, string defaultValue = null)
{
    var attr = typeof(T)
        .GetMember(enumValue.ToString())
        .First()
        .GetCustomAttributes(typeof(DescriptionAttribute), false)
        .FirstOrDefault() as DescriptionAttribute;
    return attr == null ? (defaultValue ?? enumValue.ToString()) : attr.Description;
}

This would allow the view to write simply:

MyEnum sampleEnum = MyEnum.Beer;
string description = sampleEnum.GetDescriptionOrDefault();
Sign up to request clarification or add additional context in comments.

2 Comments

Where would I put that last bit of code, in the controller? Also, will it fit into my @T construct?
@REMESQ Yes, x in your example is the enum value, right? So it would be x.GetDescription() or whatever. It should work with the T construct, since T just takes a string parameter: T(x.GetDescription().

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.