2 votes

MVC3 Enum Select List, avec des annotations d'affichage

J'ai un Html Helper qui convertit un Enum en SelectList comme ceci :

public static HtmlString EnumSelectListFor<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TProperty>> forExpression,
    object htmlAttributes,
    bool blankFirstLine) where TModel : class where TProperty : struct
{
    //MS, it its infinite wisdom, does not allow enums as a generic constraint, so we have to check here.
    if (!typeof(TProperty).IsEnum) throw new ArgumentException("This helper method requires the specified model property to be an enum type.");

    //initialize values
    var metaData = ModelMetadata.FromLambdaExpression(forExpression, htmlHelper.ViewData);
    var propertyName = metaData.PropertyName;
    var propertyValue = htmlHelper.ViewData.Eval(propertyName).ToStringOrEmpty();

    //build the select tag
    var returnText = string.Format("<select id=\"{0}\" name=\"{0}\"", HttpUtility.HtmlEncode(propertyName));
    if (htmlAttributes != null)
    {
        foreach (var kvp in htmlAttributes.GetType().GetProperties()
            .ToDictionary(p => p.Name, p => p.GetValue(htmlAttributes, null)))
        {
            returnText += string.Format(" {0}=\"{1}\"", HttpUtility.HtmlEncode(kvp.Key),
                HttpUtility.HtmlEncode(kvp.Value.ToStringOrEmpty()));
        }
    }
    returnText += ">\n";

    if (blankFirstLine)
    {
        returnText += "<option value=\"\"></option>";
    }

    //build the options tags
    foreach (var enumName in Enum.GetNames(typeof(TProperty)))
    {
        var idValue = ((int)Enum.Parse(typeof(TProperty), enumName, true)).ToString();
        var displayValue = enumName;
        var titleValue = string.Empty;
        returnText += string.Format("<option value=\"{0}\" title=\"{1}\"",
            HttpUtility.HtmlEncode(idValue), HttpUtility.HtmlEncode(titleValue));
        if (enumName == propertyValue)
        {
            returnText += " selected=\"selected\"";
        }
        returnText += string.Format(">{0}</option>\n", HttpUtility.HtmlEncode(displayValue));
    }

    //close the select tag
    returnText += "</select>";
    return new HtmlString(returnText);
}

Le problème que j'ai est que les Enums ne peuvent pas avoir d'espaces dans leurs noms, donc vous pouvez obtenir de vilaines listes de sélection si vous avez autre chose que des valeurs d'Enum d'un seul mot, comme ceci :

public enum EmployeeTypes
{
    FullTime = 1,
    PartTime,
    Vendor,
    Contractor
}

Maintenant, j'ai eu l'idée brillante, "Je sais ! Je vais utiliser les DataAnnotations pour ça !"... alors j'ai fait en sorte que mon enum ressemble à ça :

public enum EmployeeTypes
{
    [Display(Name = "Full Time")]
    FullTime = 1,
    [Display(Name = "Part Time")]
    PartTime,
    [Display(Name = "Vendor")]
    Vendor,
    [Display(Name = "Contractor")]
    Contractor
}

... mais maintenant je me gratte la tête pour savoir comment accéder à ces attributs dans ma classe d'aide. Quelqu'un peut-il m'aider à y voir plus clair ?

4voto

Darin Dimitrov Points 528142

Vous pourriez lire le DisplayAttribute du champ enum en utilisant la réflexion à l'intérieur de la boucle :

foreach (var enumName in Enum.GetNames(typeof(TProperty)))
{
    var idValue = ((int)Enum.Parse(typeof(TProperty), enumName, true)).ToString();
    var displayValue = enumName;

    // get the corresponding enum field using reflection
    var field = typeof(TProperty).GetField(enumName);
    var display = ((DisplayAttribute[])field.GetCustomAttributes(typeof(DisplayAttribute), false)).FirstOrDefault();
    if (display != null)
    {
        // The enum field is decorated with the DisplayAttribute =>
        // use its value
        displayValue = display.Name;
    }

    var titleValue = string.Empty;
    returnText += string.Format("<option value=\"{0}\" title=\"{1}\"",
        HttpUtility.HtmlEncode(idValue), HttpUtility.HtmlEncode(titleValue));
    if (enumName == propertyValue)
    {
        returnText += " selected=\"selected\"";
    }
    returnText += string.Format(">{0}</option>\n", HttpUtility.HtmlEncode(displayValue));
}

0voto

Chris Lees Points 620

J'ai toujours été partisan de la création d'une méthode d'extension pour la classe Enum afin de lire l'attribut Description et d'appeler ToDescription() sur n'importe quelle Enum. Quelque chose comme ceci.

public static class EnumExtensions
{
    public static String ToDescription(this Enum value)
    {
        FieldInfo field = value.GetType().GetField(value.ToString());
        DescriptionAttribute attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
        return attribute == null ? value.ToString() : attribute.Description;
    }   
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X