This is my enum
public class Woodshape
{
public enum eWoodShape
{
Round = 10,
Oval = 20,
Plain = 30
}
}
Now i want to add this as a dropdownlist in my controller
public ActionResult Create()
{
List<string> li = new List<string>();
FieldInfo[] myEnumFields = typeof(Woodshape.eWoodShape).GetFields();
foreach (FieldInfo myField in myEnumFields)
{
if (!myField.IsSpecialName && myField.Name.ToLower() != "notset")
{
int myValue = (int)myField.GetValue(0);
li.Add(myField.Name);
}
}
ViewBag.ddlEnumshape = new SelectList(myEnumFields, "myValue", "Name");
return View();
}
and In my view binded it as..
<div>
#Html.DropDownList("ddlEnumshape", "-Select shape-")
/<div>
but, it is showing error
System.Reflection.RtFieldInfo' does not contain a property with the name 'myValue'.
Could anyone help me
public static IEnumerable<SelectListItem> GetListEnumWrap<TEnum>()
{
var items = new List<SelectListItem>();
if (typeof(TEnum).IsEnum)
{
foreach (var value in Enum.GetValues(typeof(TEnum)).Cast<int>())
{
var name = Enum.GetName(typeof(TEnum), value);
name = string.Format("{0}", name);
items.Add(new SelectListItem() { Value = value.ToString(), Text = name });
}
}
return items;
}
use:
#Html.DropDownListFor(m => m.Type, EnumExtensions.GetListEnumWrap<Types>())
I use this method:
public static Dictionary<int, string> EnumToDictionary<T>()
{
return Enum.GetValues(typeof (T)).Cast<T>().ToDictionary(x => Convert.ToInt32(x), x => x.ToString());
}
ViewBag.ddlEnumshape = new SelectList(EnumToDictionary<Woodshape.eWoodShape>, "Key", "Value");
Related
I have an enumeration that looks like this:
BoT_DropdownValues.cs:
public class BoT_DropdownValues
{
public enum BlockSizes
{
[Display(Name = "12 Months")]
M12,
[Display(Name = "24 Months")]
M24,
[Display(Name = "36 Months")]
M36,
[Display(Name = "48 Months")]
M48,
[Display(Name = "60 Months")]
M60
}
I want to choose one of the items from "select" element:
CreateBoT.cshtml:
<div class="form-group" id="Q3_div">
#Html.DropDownListFor(m =>
m.BoT_Answers.Q3,
new SelectList(Enum.GetValues(typeof(BoT_DropdownValues.BlockSizes))),
"Select One",
new { #class = "custom-select", #id = "BoT_Answers_Q3" })
...
Problem:
This syntax gives me "M12","M24", "M36", ... in the dropdown. I'd LIKE the dropdown to show the [Display()] names: "12 Months", "24 Months", etc. to the user.
Q: Is there syntax I can use with #Html.DropDownListFor() to achieve this?
Update
Most of the answers I found involved writing a static extensions class and much extra work. I'm still looking for a "better answer", but for now this seems to give me everything I'm looking for:
#Html.DropDownListFor(m =>
m.BoT_Answers.Q3,
new List<SelectListItem>
{
new SelectListItem {Text="Select One", Value="", Selected=true },
new SelectListItem {Text="12 Months", Value="12" },
new SelectListItem {Text="24 Months", Value="24" },
new SelectListItem {Text="36 Months", Value="36" },
new SelectListItem {Text="48 Months", Value="48" },
new SelectListItem {Text="60 Months", Value="60" }
},
new { #class = "custom-select", #id = "BoT_Answers_Q3" })
Q: Can anybody think of any disadvantages to this approach?
I tested following using helper class and it worked. So valuesToDisplay = ["12 months", "24 months" etc...]:
var valuesToDisplay = GetDisplayValues();
static List<string> GetDisplayValues() {
List<string> ret = new List<string>();
var enumValues = Enum.GetValues(typeof(BlockSizes));
foreach (var value in enumValues)
{
ret.Add(EnumHelper<BlockSizes>.GetDisplayValue((BlockSizes)value));
}
return ret;
}
public static class EnumHelper<T>
{
public static IList<T> GetValues(Enum value)
{
var enumValues = new List<T>();
foreach (FieldInfo fi in value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public))
{
enumValues.Add((T)Enum.Parse(value.GetType(), fi.Name, false));
}
return enumValues;
}
public static T Parse(string value)
{
return (T)Enum.Parse(typeof(T), value, true);
}
public static IList<string> GetNames(Enum value)
{
return value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public).Select(fi => fi.Name).ToList();
}
public static IList<string> GetDisplayValues(Enum value)
{
return GetNames(value).Select(obj => GetDisplayValue(Parse(obj))).ToList();
}
private static string lookupResource(Type resourceManagerProvider, string resourceKey)
{
foreach (PropertyInfo staticProperty in resourceManagerProvider.GetProperties(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public))
{
if (staticProperty.PropertyType == typeof(System.Resources.ResourceManager))
{
System.Resources.ResourceManager resourceManager = (System.Resources.ResourceManager)staticProperty.GetValue(null, null);
return resourceManager.GetString(resourceKey);
}
}
return resourceKey; // Fallback with the key name
}
public static string GetDisplayValue(T value)
{
var fieldInfo = value.GetType().GetField(value.ToString());
var descriptionAttributes = fieldInfo.GetCustomAttributes(
typeof(DisplayAttribute), false) as DisplayAttribute[];
if (descriptionAttributes[0].ResourceType != null)
return lookupResource(descriptionAttributes[0].ResourceType, descriptionAttributes[0].Name);
if (descriptionAttributes == null) return string.Empty;
return (descriptionAttributes.Length > 0) ? descriptionAttributes[0].Name : value.ToString();
}
}
You're going to need to write a method, or use someone else's. Here's mine;
public static class EnumHelper<T> where T:struct, Enum{
public static List<(T value, string display)> Values =
typeof(T)
.GetFields(BindingFlags.Static | BindingFlags.Public)
.OrderBy(f => f.MetadataToken)
.Select(f => (
(T)f.GetValue(null),
f.GetCustomAttribute<DisplayNameAttribute>()?.DisplayName
?? f.GetCustomAttribute<DisplayAttribute>()?.Name
?? f.Name
))
.ToList();
}
public static class Extensions{
public static IEnumerable<SelectListItem> SelectList<T>(this IHtmlHelper html) where T:struct, Enum
=> EnumHelper<T>.Values.Select(v => new SelectListItem(v.display, v.value.ToString()));
}
<select asp-items="Html.SelectList<BlockSizes>()"></select>
I have an enum to keep post types :
public enum PostType
{
PostType1,
PostType2,
PostType3,
PostType4,
PostType5,
PostType6
}
I have also some user roles so based on their role, user can add post which are allowed
So I want to build dropdown list from selected enum values.
For Example :
For UserType1 my enum dropdownlist will just have posttype1, for UserType4 all are allowed.
How can I achieve this in ViewModel?
Thank you in advance...
try this, create a helper
namespace MvcApplication1.Helpers
{
public class ModelValueListProvider : IEnumerable<SelectListItem>
{
List<KeyValuePair<string, string>> innerList = new List<KeyValuePair<string, string>>();
public static readonly ModelValueListProvider PostTypeList = new PostTypeListProvider();
public static ModelValueListProvider MethodAccessEnumWithRol(int id)
{
return new PostTypeListProvider(null, id);
}
protected void Add(string value, string text)
{
string innerValue = null, innerText = null;
if (value != null)
innerValue = value.ToString();
if (text != null)
innerText = text.ToString();
if (innerList.Exists(kvp => kvp.Key == innerValue))
throw new ArgumentException("Value must be unique", "value");
innerList.Add(new KeyValuePair<string, string>(innerValue, innerText));
}
public IEnumerator<SelectListItem> GetEnumerator()
{
return new ModelValueListProviderEnumerator(innerList.GetEnumerator());
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
private struct ModelValueListProviderEnumerator : IEnumerator<SelectListItem>
{
private IEnumerator<KeyValuePair<string, string>> innerEnumerator;
public ModelValueListProviderEnumerator(IEnumerator<KeyValuePair<string, string>> enumerator)
{
innerEnumerator = enumerator;
}
public SelectListItem Current
{
get
{
var current = innerEnumerator.Current;
return new SelectListItem { Value = current.Key, Text = current.Value };
}
}
public void Dispose()
{
try
{
innerEnumerator.Dispose();
}
catch (Exception)
{
}
}
object System.Collections.IEnumerator.Current
{
get
{
return Current;
}
}
public bool MoveNext()
{
return innerEnumerator.MoveNext();
}
public void Reset()
{
innerEnumerator.Reset();
}
}
private class PostTypeListProvider : ModelValueListProvider
{
public PostTypeListProvider(string defaultText = null, int rolId = 0)
{
if (!string.IsNullOrEmpty(defaultText))
Add(string.Empty, defaultText);
if (rolId == 1)
Add(PostType.PostType1, "PostType1");
else
{
Add(PostType.PostType2, "PostType2");
Add(PostType.PostType3, "PostType3");
Add(PostType.PostType4, "PostType4");
Add(PostType.PostType5, "PostType5");
Add(PostType.PostType6, "PostType6");
}
}
public void Add(PostType value, string text)
{
Add(value.ToString("d"), text);
}
}
}
public enum PostType
{
PostType1,
PostType2,
PostType3,
PostType4,
PostType5,
PostType6
}
}
and then in your view
#Html.DropDownListFor(m => Model.idRoleuser, new SelectList(MvcApplication1.Helpers.ModelValueListProvider.MethodAccessEnumWithRol(1), "Value", "Text"))
#Html.DropDownListFor(m => Model.idRoleuser, new SelectList(MvcApplication1.Helpers.ModelValueListProvider.MethodAccessEnumWithRol(2), "Value", "Text"))
hope help you
you can do something like this.
using System.Reflection;
using System.ComponentModel;
using System.Linq.Expressions;
namespace MvcApplication7.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
}
public static class Helper {
public static HtmlString CreateDropDown(this HtmlHelper helper, Type enumType)
{
SelectList list = ToSelectList(typeof(PostType));
string Markup = #"<select>";
foreach(var item in list){
string disable = item.Value == "1" ? "disabled" : ""; //eavluate by yourself set it to disabled or not by user role just set a dummy condition
Markup += Environment.NewLine + string.Format("<option value='{0}' {1}>{2}</option>",item.Value,disable,item.Text);
}
Markup += "</select>";
return new HtmlString(Markup);
}
public static SelectList ToSelectList(Type enumType)
{
var items = new List<SelectListItem>();
foreach (var item in Enum.GetValues(enumType))
{
FieldInfo fi = enumType.GetField(item.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
var title = "";
if (attributes != null && attributes.Length > 0)
{
title = attributes[0].Description;
}
else
{
title = item.ToString();
}
var listItem = new SelectListItem
{
Value = ((int)item).ToString(),
Text = title,
};
items.Add(listItem);
}
return new SelectList(items, "Value", "Text");
}
}
public enum PostType
{
PostType1,
PostType2,
PostType3,
PostType4,
PostType5,
PostType6
}
}
and you can do in markup..
#using MvcApplication7.Controllers;
#Html.CreateDropDown(typeof(PostType))
I am getting a weird dynamic binding error when using an anonymously-typed model in RazorEngine. I know that Razor uses dynamic when the model has an anonymous type because anonymous types are internal. Here's a quick program that reproduces the error:
void Main()
{
// works fine
var model = (dynamic)new { items = new[] { Create(new { a = 2 }, 1) } };
var items = model.#items;
foreach (var item in items) {
Console.WriteLine(item.Index);
}
RazorEngine.Razor.Compile(#"
#{ var items = Model.#items; }
#foreach (var item in items) { <text>
X #item.Index
</text> } X", new { items = new[] { Create(new { a = 2 }, 1) } }.GetType(), "name");
// parse failes with RuntimeBinderException: 'System.ValueType' does not contain a definition for 'Index'
var parsed = RazorEngine.Razor.Parse(#"
#{ var items = Model.#items; }
#foreach (var item in items) { <text>
X #item.Index
</text> } X", new { items = new[] { Create(new { a = 2 }, 1) } }, "name");
Console.WriteLine(parsed);
}
public struct IndexedValue<T>
{
private readonly T _value;
private readonly int _index;
public IndexedValue(T value, int index)
{
this._index = index;
this._value = value;
}
public T Value { get { return this._value; } }
public int Index { get { return this._index; } }
}
public static IndexedValue<T> Create<T>(T item, int index) { return new IndexedValue<T>(item, index); }
Can anyone explain what's going on here?
I have got this controller:
public class NewPostController : Controller
{
List<SelectListItem> languages= new List<SelectListItem>();
public ActionResult Index()
{
ViewData["languages"] = new SelectList(languages, "Text", "Value", 1);
return View();
}
private void GetCountryList()
{
CultureInfo[] cultureList = CultureInfo.GetCultures(CultureTypes.AllCultures);
foreach (CultureInfo culture in cultureList)
{
languages.Add(new SelectListItem
{
Text = culture.DisplayName,
Value = culture.DisplayName,
});
}
}
}
The list of items should be established by their languages and be passed to the view.
#Html.DropDownList("languages",null,
"** Please Select **",
new { #class = "my-select-css-class" })
Nothing gets populated..Why?
GetCountryList()
You never call it.
I would bind the values of an enumeration with a combobox control.
I've written this code:
cboPriorLogicalOperator.DataSource = Enum.GetValues(typeof(MyEnum))
.Cast<MyEnum>()
.Select(p => new { Key = (int)p, Value = p.ToString() })
.ToList();
myComboBox.DisplayMember = "Value";
myComboBox.ValueMember = "Key";
It works well but I wonder if there is a simpler way.
I think your code is beautiful!
The only improvement would be to place the code in an Extension Method.
EDIT:
When I think about it, what you want to do is to use the Enum as in the definition and not an instance of the enum, which is required by extensions methods.
I found this question, which solves it really nicely:
public class SelectList
{
// Normal SelectList properties/methods go here
public static SelectList Of<T>()
{
Type t = typeof(T);
if (t.IsEnum)
{
var values = from Enum e in Enum.GetValues(t)
select new { ID = e, Name = e.ToString() };
return new SelectList(values, "Id", "Name");
}
return null;
}
}
// called with
var list = SelectList.Of<Things>();
Only you might want to return a Dictionary<int, string> and not a SelectList, but you get the idea.
EDIT2:
Here we go with a code example that covers the case you are looking at.
public class EnumList
{
public static IEnumerable<KeyValuePair<T, string>> Of<T>()
{
return Enum.GetValues(typeof (T))
.Cast<T>()
.Select(p => new KeyValuePair<T, string>(p, p.ToString()))
.ToList();
}
}
Or this version perhaps, where the key is an int
public class EnumList
{
public static IEnumerable<KeyValuePair<int, string>> Of<T>()
{
return Enum.GetValues(typeof (T))
.Cast<T>()
.Select(p => new KeyValuePair<int, string>(Convert.ToInt32(p), p.ToString()))
.ToList();
}
}
Why not to use:
myComboBox.DataSource = Enum.GetValues(typeof(MyEnum))
?
foreach (int r in Enum.GetValues(typeof(MyEnum)))
{
var item = new ListItem(Enum.GetName(typeof(MyEnum), r), r.ToString());
ddl.Items.Add(item);
}
I recently ran into a problem where I had a nullable enum property and needed to bind it to a ComboBox. Here is the solution I came up with:
using System;
using System.Collections.Generic;
namespace ActivitySchedule.Model
{
public class NullableEnum<T> where T : struct, IComparable
{
public string Display { get; private set; }
public T? Value { get; private set; }
public static implicit operator T?(NullableEnum<T> o)
{
return o.Value;
}
public static implicit operator NullableEnum<T>(T? o)
{
return new NullableEnum<T>
{
Display = o?.ToString() ?? "NA",
Value = o
};
}
private NullableEnum() { }
public static IEnumerable<NullableEnum<T>> GetList()
{
var items = new List<NullableEnum<T>>
{
new NullableEnum<T>
{
Display = "NA",
Value = null
}
};
var values = Enum.GetValues(typeof(T));
foreach (T v in values)
{
items.Add(v);
}
return items;
}
}
}
I wrapped the object in a Controller class and change the property's Type like so:
private MyClass myClass;
public NullableEnum<MyEnum> MyEnum
{
get { return this.myClass.MyEnum; }
set { this.myClass.MyEnum = value.Value; }
}
(it could also be a derived class and override the property)
This is how I used it:
var types = NullableEnum<MyEnum>.GetList();
this.comboBox1.DataSource = types;
this.comboBox1.DisplayMember = "Display";
this.comboBox1.ValueMember = "Value";
this.comboBox1.Bindings.Add("SelectedValue", myClassController, "MyEnum");
private void Form1_Load(object sender, EventArgs e)
{
comboBox1.DataSource = Enum.GetValues( typeof(Gender));
Array gen = Enum.GetValues(typeof(Gender));
List<KeyValuePair<string, char>> lstgender = new List<KeyValuePair<string,char>>();
foreach(Gender g in gen)
lstgender.Add(new KeyValuePair<string,char>(g.ToString(),((char)g)));
comboBox1.DataSource = lstgender;
comboBox1.DisplayMember = "key";
comboBox1.ValueMember = "value"
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(comboBox1.SelectedValue.ToString());
}
public class Student
{
public string stud_name { get; set; }
public Gender stud_gen { get; set; }
}
public enum Gender
{
Male='M',
Female='F'
}