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))
Related
I have Model in MVC like this:
public partial class Magazine
{
public int Id { get; set; }
public int MagYear { get; set; }
public int MagNo { get; set; }
public string MagSeason { get; set; }
public string MagYear2 { get; set; }
}
i want in View the MagSeason has a DropDownListFor and Fills with an
Enum Season
{
Spring =0,
Summer =1,
Autumn =2,
Winter=3
}
how should i do that?
Check out my blog post on this
http://jnye.co/Posts/4/creating-a-dropdown-list-from-an-enum-in-mvc-and-c%23
First creat an enum helper
public static class EnumHelper
{
//Creates a SelectList for a nullable enum value
public static SelectList SelectListFor<T>(T? selected) where T : struct
{
return selected == null ? SelectListFor<T>()
: SelectListFor(selected.Value);
}
//Creates a SelectList for an enum type
public static SelectList SelectListFor<T>() where T : struct
{
Type t = typeof (T);
if (t.IsEnum)
{
var values = Enum.GetValues(typeof(T)).Cast<enum>()
.Select(e => new {
Id = Convert.ToInt32(e),
Name = e.GetDescription()
});
return new SelectList(values, "Id", "Name");
}
return null;
}
//Creates a SelectList for an enum value
public static SelectList SelectListFor<T>(T selected) where T : struct
{
Type t = typeof(T);
if (t.IsEnum)
{
var values = Enum.GetValues(t).Cast<Enum>()
.Select(e => new {
Id = Convert.ToInt32(e),
Name = e.GetDescription()
});
return new SelectList(values, "Id", "Name", Convert.ToInt32(selected));
}
return null;
}
// Get the value of the description attribute if the
// enum has one, otherwise use the value.
public static string GetDescription<TEnum>(this TEnum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
if (fi != null)
{
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes.Length > 0)
{
return attributes[0].Description;
}
}
return value.ToString();
}
}
Once you have this helper class in place you can do the following.
In your controller:
//If you don't have an enum value use the type
ViewBag.DropDownList = EnumHelper.SelectListFor<MyEnum>();
//If you do have an enum value use the value (the value will be marked as selected)
ViewBag.DropDownList = EnumHelper.SelectListFor(myEnumValue);
In your View:
#Html.DropDownList("DropDownList")
Start writting your custom html helper like below explained here and change the template however you want
Enum
public enum Gender {
[Display(Name="Male", Order=0)]
Male,
[Display(Name="Female", Order=1)]
Female
}
View
#Html.EnumDropDownListFor(m => m.Gender)
Then Helper
[AttributeUsage(AttributeTargets.Field)]
public class EnumDisplayNameAttribute : System.ComponentModel.DisplayNameAttribute
{
/// <summary>
/// Sets the display name for an Enum field
/// </summary>
/// <param name="displayName">The display name value to use</param>
public EnumDisplayNameAttribute(string displayName)
: base(displayName)
{
}
}
public static class HtmlHelperExtensions
{
public static MvcHtmlString EnumDropDownList<TEnumType>(this HtmlHelper htmlHelper, string name, TEnumType value)
{
var selectItems = GetSelectItemsForEnum(typeof(TEnumType), value);
return htmlHelper.DropDownList(name, selectItems);
}
public static MvcHtmlString EnumDropDownListPlaceholder<TEnumType>(this HtmlHelper htmlHelper, string name, TEnumType value, string placeholderName = null)
{
var selectItems = GetSelectItemsForEnum(typeof(TEnumType), value);
AddPlaceHolderToSelectItems(placeholderName, selectItems);
return htmlHelper.DropDownList(name, selectItems, new { #class = "placeholder" });
}
public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes = null) where TModel : class
{
var memberExpression = expression.Body as MemberExpression;
if (memberExpression == null)
throw new InvalidOperationException("Expression must be a member expression");
var name = ExpressionHelper.GetExpressionText(expression);
var fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
ModelState currentValueInModelState;
var couldGetValueFromModelState = htmlHelper.ViewData.ModelState.TryGetValue(fullName, out currentValueInModelState);
object selectedValue = null;
if (!couldGetValueFromModelState &&
htmlHelper.ViewData.Model != null)
{
selectedValue = expression.Compile()(htmlHelper.ViewData.Model);
}
var placeholderName = PlaceholderName(memberExpression);
htmlAttributes = ApplyHtmlAttributes(htmlAttributes, placeholderName);
var selectItems = GetSelectItemsForEnum(typeof(TProperty), selectedValue).ToList();
AddPlaceHolderToSelectItems(placeholderName, selectItems);
return htmlHelper.DropDownListFor(expression, selectItems, htmlAttributes);
}
public static MvcHtmlString PlaceholderDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes = null)
where TModel : class
{
var memberExpression = expression.Body as MemberExpression;
if (memberExpression == null)
throw new InvalidOperationException("Expression must be a member expression");
IList<SelectListItem> list = selectList.ToList();
var placeholderName = PlaceholderName(memberExpression);
AddPlaceHolderToSelectItems(placeholderName, list);
htmlAttributes = ApplyHtmlAttributes(htmlAttributes, placeholderName);
return htmlHelper.DropDownListFor(expression, list, string.IsNullOrEmpty(optionLabel) ? null : optionLabel, htmlAttributes);
}
public static IList<SelectListItem> GetSelectItemsForEnum(Type enumType, object selectedValue)
{
var selectItems = new List<SelectListItem>();
if (enumType.IsGenericType &&
enumType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
enumType = enumType.GetGenericArguments()[0];
selectItems.Add(new SelectListItem { Value = string.Empty, Text = string.Empty });
}
var selectedValueName = selectedValue != null ? selectedValue.ToString() : null;
var enumEntryNames = Enum.GetNames(enumType);
var entries = enumEntryNames
.Select(n => new
{
Name = n,
EnumDisplayNameAttribute = enumType
.GetField(n)
.GetCustomAttributes(typeof(EnumDisplayNameAttribute), false)
.OfType<EnumDisplayNameAttribute>()
.SingleOrDefault() ?? new EnumDisplayNameAttribute("")
})
.Select(e => new
{
Value = e.Name,
DisplayName = e.EnumDisplayNameAttribute.DisplayName ?? e.Name
})
.OrderBy(e => e.DisplayName)
.Select(e => new SelectListItem
{
Value = e.Value,
Text = e.DisplayName,
Selected = e.Value == selectedValueName
});
selectItems.AddRange(entries);
return selectItems;
}
public static IEnumerable<string> GetNamesForEnum(Type enumType, object selectedValue)
{
if (enumType.IsGenericType &&
enumType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
enumType = enumType.GetGenericArguments()[0];
}
var enumEntryNames = Enum.GetNames(enumType);
var entries = enumEntryNames
.Select(n => new
{
Name = n,
EnumDisplayNameAttribute = enumType
.GetField(n)
.GetCustomAttributes(typeof(EnumDisplayNameAttribute), false)
.OfType<EnumDisplayNameAttribute>()
.SingleOrDefault() ?? new EnumDisplayNameAttribute("")
})
.Select(e => new
{
Value = e.Name,
DisplayName = e.EnumDisplayNameAttribute.DisplayName ?? e.Name
})
.OrderBy(e => e.DisplayName)
.Select(e => e.Value);
return entries;
}
static string PlaceholderName(MemberExpression memberExpression)
{
var placeholderName = memberExpression.Member
.GetCustomAttributes(typeof(EnumDisplayNameAttribute), true)
.Cast<EnumDisplayNameAttribute>()
.Select(a => a.DisplayName)
.FirstOrDefault();
return placeholderName;
}
static void AddPlaceHolderToSelectItems(string placeholderName, IList<SelectListItem> selectList)
{
if (!selectList.Where(i => i.Text == string.Empty).Any())
selectList.Insert(0, new SelectListItem { Selected = false, Text = placeholderName, Value = string.Empty });
if (!selectList.Any() || selectList[0].Text != string.Empty) return;
selectList[0].Value = "";
selectList[0].Text = placeholderName;
}
static IDictionary<string, object> ApplyHtmlAttributes(IDictionary<string, object> htmlAttributes, string placeholderName)
{
if (!string.IsNullOrEmpty(placeholderName))
{
if (htmlAttributes == null)
{
htmlAttributes = new Dictionary<string, object>();
}
if (!htmlAttributes.ContainsKey("class"))
htmlAttributes.Add("class", "placeholder");
else
{
htmlAttributes["class"] += " placeholder";
}
}
return htmlAttributes;
}
}
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?
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");
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'
}
I have run into a situation where I need to compare two different lists to each other and I am wondering what the best method is for doing this? I thought something like this would work but it doesn't and I can't figure out why. The Linq query is returning records it shouldn't. This is my first run at trying to figure something like this out so it is undoubtedly messy.
private static List<ColumnDefinition> FindTableStructureUpdates(List<ColumnDefinition> colDefs, List<ColumnDefinition> tblCols)
{
List<ColumnDefinition> ColsToUpdate = new List<ColumnDefinition>();
for (int i = 0; i < colDefs.Count; ++i)
{
string colDefName = colDefs[i].ColName;
string colDefDataType = colDefs[i].ColType;
string colDefAttribute = colDefs[i].ColAttributes;
var query = from tbl in tblCols
where tbl.ColName != colDefName && tbl.ColType != colDefDataType && tbl.ColAttributes != colDefAttribute
select new { colDefName, colDefDataType, colDefAttribute };
if (query.Count() > 0)
{
foreach (var item in query)
{
ColsToUpdate.Add(new ColumnDefinition(item.colDefName, item.colDefDataType, item.colDefAttribute));
}
}
}
return ColsToUpdate;
Any suggestions would be great.
Thanks.
IEquatable Implementation??
#region IEquatable<ColumnDefinition> Members
public bool Equals(ColumnDefinition other)
{
if (this.ColName.Equals(other.ColName) && this.ColType.Equals(other.ColType) && this.ColAttributes.Equals(other.ColAttributes))
return true;
return false;
}
Can't you use Enumerable.Except ?
public static IEnumerable<TSource> Except<TSource>(
this IEnumerable<TSource> first,
IEnumerable<TSource> second
)
More details.
An example tested in Snippet Compiler
using System;
using System.Linq;
using System.Collections.Generic;
class ColumnDefinition : IEquatable<ColumnDefinition>
{
public string Name { get; set; }
public string Type { get; set; }
public string Attr { get; set; }
public ColumnDefinition()
{
Name = string.Empty;
Type = string.Empty;
Attr = string.Empty;
}
public bool Equals(ColumnDefinition other)
{
return Name.Equals(other.Name) && Type.Equals(other.Type) && Attr.Equals(other.Attr);
}
public override bool Equals(object value)
{
return (value is ColumnDefinition) ? Equals(value as ColumnDefinition) : false;
}
public override int GetHashCode()
{
return Name.GetHashCode() ^ Type.GetHashCode() ^ Attr.GetHashCode();
}
public override string ToString()
{
return string.Concat("{", Name, ":", Type, ":", Attr, "}");
}
}
public class Program
{
public static void Main(string[] args)
{
try
{
MyMain(args);
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
Console.ReadKey();
}
}
public static void MyMain(string[] args)
{
var list1 = new []
{
new ColumnDefinition { Name = "foo", Type = "int", Attr = "0" },
new ColumnDefinition { Name = "bar", Type = "int", Attr = "1" },
};
var list2 = new []
{
new ColumnDefinition { Name = "foo", Type = "int", Attr = "0" },
new ColumnDefinition { Name = "bar", Type = "string", Attr = "1" },
};
foreach (var changed in Enumerable.Except(list1, list2))
{
Console.WriteLine(changed);
}
}
}