Problem:
Need to bind a strongly typed model which has a Gender as enum property. Also i like to show a Display text from a Resource file.
My Model is
public enum GenderViewModel
{
[Display(Name = "Male", ResourceType = typeof(Resources.Global), Order = 0)]
Male,
[Display(Name = "Female", ResourceType = typeof(Resources.Global), Order = 1)]
Female
}
Initially, I tried following http://romikoderbynew.com/2012/02/23/asp-net-mvc-rendering-enum-dropdownlists-radio-buttons-and-listboxes/
But it was bit complex and i was unable to correct my HTML however i want.
Then i had a look of simple and easy implementation from stackoverflow, pass enum to html.radiobuttonfor MVC3
and used a HtmlHelper in cshtml like below
@Html.RadioButtonForEnum(m => m.Gender)
HTML Produced
<label for="_Gender_Male">
<input type="radio" value="Male" name="Gender" id="_Gender_Male"
data-val-required="Gender is required" data-val="true" checked="checked">
<span class="radiotext">Male</span>
</label>
<label for="_Gender_Female">
<input type="radio" value="Female" name="Gender" id="_Gender_Female">
<span class="radiotext">Female</span></label>
It really simple and works well for me. But i am not getting values
from Resource files. My application is multilingual and I use a Global
Resource file for different language support.
Issue:
Male displayed should be Man and Female displayed should be Kvinna should be from Resource file, as my current culture is sv-se
Could any one help/ provide a simple solution which has a good control over HTML?
All you have to do is adapt my original helper
so that it takes into account the DisplayAttribute
:
public static class HtmlExtensions
{
public static MvcHtmlString RadioButtonForEnum<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression
)
{
var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
if (!metaData.ModelType.IsEnum)
{
throw new ArgumentException("This helper is intended to be used with enum types");
}
var names = Enum.GetNames(metaData.ModelType);
var sb = new StringBuilder();
var fields = metaData.ModelType.GetFields(
BindingFlags.Static | BindingFlags.GetField | BindingFlags.Public
);
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();
var field = fields.Single(f => f.Name == name);
var label = name;
var display = field
.GetCustomAttributes(typeof(DisplayAttribute), false)
.OfType<DisplayAttribute>()
.FirstOrDefault();
if (display != null)
{
label = display.GetName();
}
sb.AppendFormat(
"<label for=\"{0}\">{1}</label> {2}",
id,
HttpUtility.HtmlEncode(label),
radio
);
}
return MvcHtmlString.Create(sb.ToString());
}
}
Now if you have decorated some of the enum values with the DisplayAttribute, the values will come from the resource file.
You should replace in the extension method were it uses name
for the <label>
to use the resource you would like.
You should use a code kind of this one I adapted from here:
var type = typeof(metaData.ModelType);
var memInfo = type.GetMember(name);
var attributes = memInfo[0].GetCustomAttributes(typeof(DisplayAttribute), false);
var description = ((DisplayAttribute)attributes[0]).GetDescription();
And then put description
into the <label>
.
I've not tested it!