Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enum with integer strings

I have a public enum like so:

public enum occupancyTimeline
{
    TwelveMonths,
    FourteenMonths,
    SixteenMonths,
    EighteenMonths
}

which I will be using for a DropDown menu like so:

@Html.DropDownListFor(model => model.occupancyTimeline, 
   new SelectList(Enum.GetValues(typeof(CentralParkLCPreview.Models.occupancyTimeline))), "")

Now I am looking for away to have my values like so

12 Months, 14 Months, 16 Months, 18 Months instead of TweleveMonths, FourteenMonths, SixteenMonths, EighteenMonths

How would I accomplish this?

like image 667
user979331 Avatar asked Sep 06 '16 17:09

user979331


People also ask

Can enum values be strings?

Given those limitations, the enum value alone is not suitable for human-readable strings or non-string values. In this tutorial, we'll use the enum features as a Java class to attach the values we want.

Can we use integer in enum?

No, we can have only strings as elements in an enumeration.

Is enum an int or string?

Enums are objects, not integers or strings. Like any objects, they can optionally wrap other values.

Can enum have multiple values?

Learn to create Java enum where each enum constant may contain multiple values. We may use any of the values of the enum constant in our application code, and we should be able to get the enum constant from any of the values assigned to it.


4 Answers

I've made myself an extension method, which I now use in every project:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web.Mvc;

namespace App.Extensions
{
    public static class EnumExtensions
    {
        public static SelectList ToSelectList(Type enumType)
        {
            return new SelectList(ToSelectListItems(enumType));
        }

        public static List<SelectListItem> ToSelectListItems(Type enumType, Func<object, bool> itemSelectedAction = null)
        {
            var arr = Enum.GetValues(enumType);
            return (from object item in arr
                    select new SelectListItem
                    {
                        Text = ((Enum)item).GetDescriptionEx(typeof(MyResources)),
                        Value = ((int)item).ToString(),
                        Selected = itemSelectedAction != null && itemSelectedAction(item)
                    }).ToList();
        }

        public static string GetDescriptionEx(this Enum @this)
        {
            return GetDescriptionEx(@this, null);
        }

        public static string GetDescriptionEx(this Enum @this, Type resObjectType)
        {
            // If no DescriptionAttribute is present, set string with following name
            // "Enum_<EnumType>_<EnumValue>" to be the default value.
            // Could also make some code to load value from resource.

            var defaultResult = $"Enum_{@this.GetType().Name}_{@this}";

            var fi = @this.GetType().GetField(@this.ToString());
            if (fi == null)
                return defaultResult;

            var customAttributes = fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
            if (customAttributes.Length <= 0 || customAttributes.IsNot<DescriptionAttribute[]>())
            {
                if (resObjectType == null)
                    return defaultResult;

                var res = GetFromResource(defaultResult, resObjectType);
                return res ?? defaultResult;
            }

            var attributes = (DescriptionAttribute[])customAttributes;
            var result = attributes.Length > 0 ? attributes[0].Description : defaultResult;
            return result ?? defaultResult;
        }

        public static string GetFromResource(string defaultResult, Type resObjectType)
        {
            var searchingPropName = defaultResult;
            var props = resObjectType.GetProperties();
            var prop = props.FirstOrDefault(t => t.Name.Equals(searchingPropName, StringComparison.InvariantCultureIgnoreCase));
            if (prop == null)
                return defaultResult;
            var res = prop.GetValue(resObjectType) as string;
            return res;
        }

        public static bool IsNot<T>(this object @this)
        {
            return !(@this is T);
        }
    }
}

And then use it like this (in a View.cshtml, for example) (code is broken in two lines for clarity; could also make oneliner):

// A SelectList without default value selected
var list1 = EnumExtensions.ToSelectListItems(typeof(occupancyTimeline));
@Html.DropDownListFor(model => model.occupancyTimeline, new SelectList(list1), "")

// A SelectList with default value selected if equals "DesiredValue"
// Selection is determined by lambda expression as a second parameter to
// ToSelectListItems method which returns bool.
var list2 = EnumExtensions.ToSelectListItems(typeof(occupancyTimeline), item => (occupancyTimeline)item == occupancyTimeline.DesiredValue));
@Html.DropDownListFor(model => model.occupancyTimeline, new SelectList(list2), "")

Update

Based on Phil's suggestion, I've updated above code with possibility to read enum's display value from some resource (if you have any). Name of item in a resource should be in a form of Enum_<EnumType>_<EnumValue> (e.g. Enum_occupancyTimeline_TwelveMonths). This way you can provide text for your enum values in resource file without decorating your enum values with some attributes. Type of resource (MyResource) is included directly inside ToSelectItems method. You could extract it as a parameter of an extension method.

The other way of naming enum values is applying Description attribute (this works without adapting the code to the changes I've made). For example:

public enum occupancyTimeline
{
    [Description("12 Months")]
    TwelveMonths,
    [Description("14 Months")]
    FourteenMonths,
    [Description("16 Months")]
    SixteenMonths,
    [Description("18 Months")]
    EighteenMonths
}
like image 109
Jure Avatar answered Oct 20 '22 03:10

Jure


You might check this link

his solution was targeting the Asp.NET , but by easy modification you can use it in MVC like

/// <span class="code-SummaryComment"><summary></span>
/// Provides a description for an enumerated type.
/// <span class="code-SummaryComment"></summary></span>
[AttributeUsage(AttributeTargets.Enum | AttributeTargets.Field, 
 AllowMultiple = false)]
public sealed class EnumDescriptionAttribute :  Attribute
{
   private string description;

   /// <span class="code-SummaryComment"><summary></span>
   /// Gets the description stored in this attribute.
   /// <span class="code-SummaryComment"></summary></span>
   /// <span class="code-SummaryComment"><value>The description stored in the attribute.</value></span>
   public string Description
   {
      get
      {
         return this.description;
      }
   }

   /// <span class="code-SummaryComment"><summary></span>
   /// Initializes a new instance of the
   /// <span class="code-SummaryComment"><see cref="EnumDescriptionAttribute"/> class.</span>
   /// <span class="code-SummaryComment"></summary></span>
   /// <span class="code-SummaryComment"><param name="description">The description to store in this attribute.</span>
   /// <span class="code-SummaryComment"></param></span>
   public EnumDescriptionAttribute(string description)
       : base()
   {
       this.description = description;
   }
}

the helper that will allow you to build a list of Key and Value

/// <span class="code-SummaryComment"><summary></span>
/// Provides a static utility object of methods and properties to interact
/// with enumerated types.
/// <span class="code-SummaryComment"></summary></span>
public static class EnumHelper
{
   /// <span class="code-SummaryComment"><summary></span>
   /// Gets the <span class="code-SummaryComment"><see cref="DescriptionAttribute" /> of an <see cref="Enum" /></span>
   /// type value.
   /// <span class="code-SummaryComment"></summary></span>
   /// <span class="code-SummaryComment"><param name="value">The <see cref="Enum" /> type value.</param></span>
   /// <span class="code-SummaryComment"><returns>A string containing the text of the</span>
   /// <span class="code-SummaryComment"><see cref="DescriptionAttribute"/>.</returns></span>
   public static string GetDescription(Enum value)
   {
      if (value == null)
      {
         throw new ArgumentNullException("value");
      }

      string description = value.ToString();
      FieldInfo fieldInfo = value.GetType().GetField(description);
      EnumDescriptionAttribute[] attributes =
         (EnumDescriptionAttribute[])
       fieldInfo.GetCustomAttributes(typeof(EnumDescriptionAttribute), false);

      if (attributes != null && attributes.Length > 0)
      {
         description = attributes[0].Description;
      }
      return description;
   }

   /// <span class="code-SummaryComment"><summary></span>
   /// Converts the <span class="code-SummaryComment"><see cref="Enum" /> type to an <see cref="IList" /> </span>
   /// compatible object.
   /// <span class="code-SummaryComment"></summary></span>
   /// <span class="code-SummaryComment"><param name="type">The <see cref="Enum"/> type.</param></span>
   /// <span class="code-SummaryComment"><returns>An <see cref="IList"/> containing the enumerated</span>
   /// type value and description.<span class="code-SummaryComment"></returns></span>
   public static IList ToList(Type type)
   {
      if (type == null)
      {
         throw new ArgumentNullException("type");
      }

      ArrayList list = new ArrayList();
      Array enumValues = Enum.GetValues(type);

      foreach (Enum value in enumValues)
      {
         list.Add(new KeyValuePair<Enum, string>(value, GetDescription(value)));
      }

      return list;
   }
}

then you decorate your enum as

public enum occupancyTimeline
{
    [EnumDescriptionAttribute ("12 months")]
    TwelveMonths,
    [EnumDescriptionAttribute ("14 months")]
    FourteenMonths,
    [EnumDescriptionAttribute ("16 months")]
    SixteenMonths,
    [EnumDescriptionAttribute ("18 months")]
    EighteenMonths
}

you can use it in the controller to fill the drop down list as

ViewBag.occupancyTimeline =new SelectList( EnumHelper.ToList(typeof(occupancyTimeline)),"Value","Key");

and in your view, you can use the following

@Html.DropdownList("occupancyTimeline")

hope it will help you

like image 27
Monah Avatar answered Oct 20 '22 03:10

Monah


Make extension Description for enumeration

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.ComponentModel;
public static class EnumerationExtensions
{
//This procedure gets the <Description> attribute of an enum constant, if any.
//Otherwise, it gets the string name of then enum member.
[Extension()]
public static string Description(Enum EnumConstant)
{
    Reflection.FieldInfo fi = EnumConstant.GetType().GetField(EnumConstant.ToString());
    DescriptionAttribute[] attr = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
    if (attr.Length > 0) {
        return attr(0).Description;
    } else {
        return EnumConstant.ToString();
    }
}

}
like image 22
Tony Dong Avatar answered Oct 20 '22 03:10

Tony Dong


You can use EnumDropDownListFor for this purpose. Here is an example of what you want. (Just don't forget to use EnumDropDownListFor you should use ASP MVC 5 and Visual Studio 2015.):

Your View:

@using System.Web.Mvc.Html
@using WebApplication2.Models
@model WebApplication2.Models.MyClass

@{
    ViewBag.Title = "Index";
}

@Html.EnumDropDownListFor(model => model.occupancyTimeline)

And your model:

public enum occupancyTimeline
{
    [Display(Name = "12 months")]
    TwelveMonths,
    [Display(Name = "14 months")]
    FourteenMonths,
    [Display(Name = "16 months")]
    SixteenMonths,
    [Display(Name = "18 months")]
    EighteenMonths
}

Reference: What's New in ASP.NET MVC 5.1

like image 32
Salah Akbari Avatar answered Oct 20 '22 03:10

Salah Akbari