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.

McGarnagle
  • 101,349
  • 31
  • 229
  • 260
REMESQ
  • 1,190
  • 2
  • 26
  • 60

1 Answers1

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();
Community
  • 1
  • 1
McGarnagle
  • 101,349
  • 31
  • 229
  • 260
  • Where would I put that last bit of code, in the controller? Also, will it fit into my `@T` construct? – REMESQ Aug 24 '13 at 05:07
  • @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()`. – McGarnagle Aug 24 '13 at 06:11