Accessing assigned variable items within combobox selected item - c#

I am using a combobox to add data to a datagrid with the coding below. What I want to achieve is accessing all of the 'item' properties/information that's connected to that selected item's id and then setting all of that information to a class (ExtraDisplayItems). How would I go about doing this?
var item = cmbAddExtras.SelectedItem;
if (item != null)
dgAddExtras.Items.Add(item);
Here is my class:
public class ExtraDisplayItems
{
public int ItemId { get; set; }
public string ItemCode { get; set; }
public string ItemDescription { get; set; }
}
What I have gotten to work with databinding is displaying each of the item's 'id' in the datagrid and not any further.
EDIT: I am trying to use the same type that I used in my comboboxes, but I am having a bit of trouble.
I am just giving the extra information if it might help. Here is where I get all the information from my WCF service and then setting the information to my DisplayItems class in my WPF application:
private async Task LoadItems(TruckServiceClient TSC, QuoteOptionType type, ComboBox combobox)
{
List<DisplayItems> displayItems = new List<DisplayItems>();
foreach (var item in await TSC.GetQuoteOptionListAsync(type))
displayItems.Add(new DisplayItems { Id = item.Key, Name = item.Value });
combobox.ItemsSource = (displayItems.ToArray());
}
Then in the method below, I load the data from my LoadItems method into the specific comboboxes:
private async void QuoteWindow_Loaded(object sender, RoutedEventArgs e)
{
using (TruckServiceClient TSC = new TruckServiceClient())
{
await LoadItems(TSC, QuoteOptionType.BodyType, cmbBodyType);
...
await LoadItems(TSC, QuoteOptionType.RearDropSide, cmbRearDropsideHeight);
await LoadItems(TSC, QuoteOptionType.Extras, cmbAddExtras); //Extras
}
//cmbAddExtras.SelectionChanged += cmbAddExtras_SelectionChanged;
}
In my final code snippet I am trying to set the cmbAddExtras.SelectedItem to my Type (wich I think is: QuoteOptionType.Extras).
I am trying to set the SelectedItem as below, but with no clue how to do it :(
var item = cmbAddExtras.SelectedItem as await QuoteOptionType.Extras;
or
var item = cmbAddExtras.SelectedItem as await LoadItems(TSC, QuoteOptionType.Extras, cmbAddExtras);
I am getting the errors:
'await' cannot be used as an identifier within an async method or
lamba expression
&
; expected
Because this call is not awaited, execution of the current method continues before the call is complicated. Consider applying the 'await' operator to the result of the call.
As you can clearly see that I have NO clue what I am doing. Also here is my class where I create my QuoteOptionType class/enum. This is from my WCF application:
[DataContract]
[Flags]
public enum QuoteOptionType
{
[EnumMember]
BodyType,
[EnumMember]
Chassis,
[EnumMember]
PaintColor,
[EnumMember]
DropSide,
[EnumMember]
Floor,
[EnumMember]
RearDropSide,
[EnumMember]
Extras
}
2nd EDIT: Here I am using the Dictionary
public Dictionary<int, string> GetQuoteOptionList(QuoteOptionType optionType)
{
Dictionary<int, string> result = new Dictionary<int, string>();
using (TruckDb db = new TruckDb())
{
switch (optionType)
{
case QuoteOptionType.BodyType:
db.BodyTypes.ToList().ForEach(x => result.Add(x.Id, x.Name));
break;
...
case QuoteOptionType.RearDropSide:
db.RearDropSides.ToList().ForEach(x => result.Add(x.Id, x.Name));
break;
case QuoteOptionType.Extras: // x.StockItem throws out the error: No overload for method 'Add' takes 3 arguments
db.Extras.ToList().ForEach(x => result.Add(x.Id, x.Description, x.StockItem));
break;
default:
throw new ArgumentException("The option that was selected does not have a corresponding list.");
}
}
return result;
}

What you have to do is cast the SelectedItem to the appropiate type. For instance:
var item = cmbAddExtras.SelectedItem as DisplayItems;
if (item != null)
{
var displayItem = new ExtraDisplayItems();
displayItem.ItemId = item.Id;
displayItem.ItemCode = GetCode(item);
displayItem.ItemDescription = item.Name;
DoStuffWithYourDisplayItem(displayItem);
dgAddExtras.Items.Add(item);
}
Even if SelectedItem returns an object, internally that object is actually your class (DisplayItems), so you can cast it and use it normally.

Related

Is it possible to have a ComboBox DisplayMember set to a property of an object in a list?

I have a ComboBox being populated where each object in ComboBox.Items is a List of objects. Currently the ComboBox displays "(Collection)" for each Item.
Is it possible to have the ComboBox display a member of the first object in the List that comprises an Item of the ComboBox?
I am currently populating the ComboBox items by the following:
foreach(List<SorterIdentifier> sorterGroup in m_AvailableSorterGroups)
{
// There are conditions that may result in the sorterGroup not being added
comboBoxSorterSelect.Items.Add(sorterGroup);
}
//comboBoxSorterSelect.DataSource = m_AvailableSorterGroups; // Not desired due to the comment above.
//comboBoxSorterSelect.DisplayMember = "Count"; //Displays the Count of each list.
The value that I would like to have displayed in the ComboBox can be referenced with:
((List<SorterIdentifier>)comboBoxSorterSelect.Items[0])[0].ToString();
((List<SorterIdentifier>)comboBoxSorterSelect.Items[0])[0].DisplayName; // public member
You can create an object wrapper and override the ToString() method:
public class ComboBoxSorterIdentifierItem
{
public List<SorterIdentifier> Items { get; }
public override string ToString()
{
if ( Items == null || Items.Count == 0) return "";
return Items[0].ToString();
}
public BookItem(List<SorterIdentifier> items)
{
Items = items;
}
}
You should override the SorterIdentifier.ToString() too to return what you want like DisplayName.
Now you can add items in the combobox like this:
foreach(var sorterGroup in m_AvailableSorterGroups)
{
item = new ComboBoxSorterIdentifierItem(sorterGroup);
comboBoxSorterSelect.Items.Add(item);
}
And to use the selected item for example, you can write:
... ((ComboBoxSorterIdentifierItem)comboBoxSorterSelect.SelectedItem).Item ...
I could imagine a few ways to do this... you could create a class that extends List<T>, so you have an opportunity to define the value you'd like to display.
public class SortedIdentifier
{
public string Name { get; set; }
}
public class SortedIdentifiers : List<SortedIdentifier>
{
public string SortedIdentifierDisplayValue
{
get { return this.FirstOrDefault()?.Name ?? "No Items"; }
}
}
Then use the new class like this:
comboBox1.DisplayMember = "SortedIdentifierDisplayValue";
var list = new SortedIdentifiers { new SortedIdentifier { Name = "John" } };
comboBox1.Items.Add(list);

Filtering ListBox using combobox and LINQ

I have a winform that includes a ListBox and a Combobox. In this ListBox appears a clients list on first run.
I want to filter the "Clients" in the ListBox with a Combobox.
To fill the ListBox using the string selected in the Combobox i'm using :
private void FillListBox()
{
this.lstClient.Items.Clear();
foreach (Client c in this.client)
{
if (this.cBox.Text == "All")
this.lstClient.Items.Add(c.ToString());
else
if (this.cBox.Text == "Retail" && c.GetType() == typeof(RetailClient))
this.lstClient.Items.Add(c.ToString());
}
this.lstClient.Sorted = true;
}
After that i call this method from the event of the ComboBox :
private void cBox_TextChanged(object sender, EventArgs e)
{
this.FillListBox();
}
It works "great" but my code is not really dynamic and too long (lots of differents clients) that's why i would like to use LINQ.
I read on microsoft's documentation but i'm pretty confused on how using it.
Does anyone have some times to show me the way ?
Adding infos :
My form :
I select the type i want in the ComboBox :
The result :
Thanks
Ok let's give it a try. If you want to implement filtering you should think about a proper structure how to represent your filter criterion. In this case you have a label in your combobox which is bound to a unique filter criterion. This could be represented by a custom class:
public class SortingRepresentation
{
public string DisplayLabel { get; set; }
public Type ClientType { get; set; }
}
Now you can create a List of those criteria and shove it into the combobox:
List<SortingRepresentation> sortingFields = new List<SortingRepresentation>();
public Form1()
{
sortingFields.Add(new SortingRepresentation{ DisplayLabel = "All", TypeCriterion = typeof(Client) });
sortingFields.Add(new SortingRepresentation{ DisplayLabel = "Only Retail", TypeCriterion = typeof(Client_A) });
sortingFields.Add(new SortingRepresentation{ DisplayLabel = "Only Wholesale", TypeCriterion = typeof(Client_B) });
sortingFields.Add(new SortingRepresentation{ DisplayLabel = "Only Human Wholesale", TypeCriterion = typeof(Client_C) });
cBox.DisplayMember = "DisplayLabel";
cBox.DataSource = sortingFields;
}
When the selection changes in the combobox you can catch now the selected item (which will be of type SortingRepresentation and pass it as a filter to FillListBox:
private void cBox_SelectedIndexChanged(object sender, EventArgs e)
{
FillListBox((SortingRepresentation)cBox.SelectedItem);
}
Now you can use the Type TypeCriterion inside this object to filter your list:
private void FillListBox(SortingRepresentation sortcriterion)
{
this.lstClient.DataSource = null;
this.lstClient.DataSource = client
.Where(x => x.GetType() == sortcriterion.TypeCriterion || // either you are of this type
x.GetType().BaseType == sortcriterion.TypeCriterion // or your parent is of this type
).ToList();
}
Since you are using a listbox, you can bind the sorted list directly to the DataSource and be done with it. For the proper display, you need to override the ToString method in your Client class and the ListBox will take care of the display accordingly. But as I see you've done it already

I'm retrieving a value for a combobox with custom class items but I can't make it show the item

I wanted to have items and hidden values which I could call later so I used this Article to create my custom items.
But now that I'm calling one value I cannot make it show the proper item. The combobox stays null.
if (reader.HasRows)
{
reader.Read();
namebox.Text = reader["c_Name"].ToString();
lastbox.Text = reader["c_LastName"].ToString();
genderbox.SelectedItem = reader["c_gender"].ToString();
}
Here is what I add to my combobox and what I want to show accoring to what value I get from the reader
private void editcust_Load(object sender, EventArgs e)
{
genderbox.Items.Add(new ComboBoxItem("male", "1"));
genderbox.Items.Add(new ComboBoxItem("female", "0"));
}
Please let me know if I need to add more code or provide more information.
I'm a junior developer so please excuse my terrible mistakes and bad formulation.
First, override Equals and GetHashCode methods in your class:
public class ComboBoxItem()
{
string displayValue;
string hiddenValue;
//Constructor
public ComboBoxItem (string d, string h)
{
displayValue = d;
hiddenValue = h;
}
//Accessor
public string HiddenValue
{
get
{
return hiddenValue;
}
}
public override bool Equals(object obj)
{
ComboBoxItem item = obj as ComboBoxItem;
if (item == null)
{
return false;
}
return item.hiddenValue == this.hiddenValue;
}
public override int GetHashCode()
{
if (this.hiddenValue == null)
{
return 0;
}
return this.hiddenValue.GetHashCode();
}
//Override ToString method
public override string ToString()
{
return displayValue;
}
}
Then assign a new Item to the SelectedItem property:
genderbox.SelectedItem = new ComboBoxItem(string.Empty, reader["c_gender"].ToString());
When you assign a value to the SelectedItem property of ComboBox, it looks in it's items collection and tries to find an item that is equal to the assigned value. If it find an item equal to the value, that item gets selected. In the process, comparison is done by the Equals method of each item.
By overriding the method, you tell ComboBox to compare items using the "hiddenValue" field, so when you assign a new item with ite's hiddenValue set, combobox can find it in it's items collection. If you don't do that, equality comparison will be done using object references instead.
Use the DisplayMember & ValueMember properties of the ComboBox-Class and assign a DataSource.
ie. Your Data Class:
private class yourDataClass
{
public string DisplayMemberProperty { get; set; }
public int IDMember { get; set; }
}
Assign the datasource with values to the combobox
var dataSource = new ArrayList();
dataSource.Add(new yourDataClass() { DisplayMemberProperty = "Hello", IDMember = 1 });
dataSource.Add(new yourDataClass() { DisplayMemberProperty = "Hello2", IDMember = 2 });
dataSource.Add(new yourDataClass() { DisplayMemberProperty = "Hello3", IDMember = 2 });
this.comboBox1.DataSource = dataSource;
this.comboBox1.DisplayMember = "DisplayMemberProperty";
this.comboBox1.ValueMember = "IDMember";
Retreive the selected value...
var value = this.comboBox1.SelectedValue;
Agreed the question is unclear but if you mean that this call fails:
genderbox.SelectedItem = reader["c_gender"].ToString();
It's probably because that you need to use the same kind of value that you originally populated the list with.
i.e. if you populated it with instances of class x you need to set selectedItem to an instance of class x.

TList and Creating New Class that is a List of Class of my own is updating Tlist

I have a WizardInfo class which as several TLists as properties, this then populates as the user goes through the wizard on the last screen I query the Tlists and make them into Lists and private fields
I then create Lists of DefaultItems from these lists. This is my own class and as name and Id as its property.
He is some code
public class DefaultItem
{
public int ID {get;set;}
public string Name {get;set;}
}
private List<DefaultItem> _defaultList = null;
_defaultList = new List<DefaultItem>();
defaultValue = PopulateDefaultList(_asmgps, defaultList);
private int PopulateDefaultList(
List<ASGMP> asmgps,
ref List<DefaultItem> defaultList)
{
int isdefault = -1;
foreach (ASGMP asgmp in asgmps)
{
if (asgmp.IsChecked)
{
if (asgmp.IsDefault)
{
isdefault = asgmp.ID;
}
DefaultItem defaultItem = new DefaultItem();
defaultItem.ID = asgmp.ID;
defaultItem.Name = GetMPTName(asgmp.ID);
defaultList.Add(defaultItem);
}
}
return isdefault;
}
private string GetMPTName(int ID)
{
try
{
SGMP sgmp = DataRepository.SGMPProvider.GetByASGMPID(ID)
if (serviceGroupMailPresentation != null)
{
MPT mpt DataRepository.MPTProvider.GetByMPTID(SGMP.MPTID);
if (mailPresentationType != null)
{
return mpt.Name;
}
}
return string.Empty;
}
catch (Exception ex)
{
WindowsEventLog.Write(ex);
throw;
}
}
The problem i am having is when i remove a item from the defaultList it affects asgmp.
I have found the answer. When I get the mpt name I get asgmp from the database this is where Codesmith does a strange thing and connects the usage of the List and the DefaultList. By querying the original List instead of going to the database it now works fine.
It is being removed because List<T> is derived from object, and is a Reference type. Reference types are passed by reference, i.e. when you pass your list, you are passing a pointer to its location in memory. So any changed you make on the copied reference, will also be reflected on the original object.
In order to make a copy you can change this like:
defaultValue = PopulateDefaultList(_asmgps, defaultList);
to this:
defaultValue = PopulateDefaultList(_asmgps.ToList(), defaultList);
This will enumerate the collection as IEnumerable<T> and return is as a list. This will effectivlly create a copy.
erm, instead of PopulateDefaultList why not just do,
var defaultList = asgmps
.Where(asgmp => asgmp.IsChecked)
.Select(asgmp => new
{
IsDefault = asgmp.IsDefault,
Item = new DefaultItem
{
ID = asgmp.ID,
Name = GetMPTName(asgmp.ID)
}
}).ToList();
of course, naming a collection defaultList that contains non-defaults seems counter intuitive.
I found out that this is because of ntiers instead of using the database the to get the ID I should of used the in List of T in

How do you bind an Enum to a DropDownList control in ASP.NET?

Let's say I have the following simple enum:
enum Response
{
Yes = 1,
No = 2,
Maybe = 3
}
How can I bind this enum to a DropDownList control so that the descriptions are displayed in the list as well as retrieve the associated numeric value (1,2,3) once an option has been selected?
I probably wouldn't bind the data as it's an enum, and it won't change after compile time (unless I'm having one of those stoopid moments).
Better just to iterate through the enum:
Dim itemValues As Array = System.Enum.GetValues(GetType(Response))
Dim itemNames As Array = System.Enum.GetNames(GetType(Response))
For i As Integer = 0 To itemNames.Length - 1
Dim item As New ListItem(itemNames(i), itemValues(i))
dropdownlist.Items.Add(item)
Next
Or the same in C#
Array itemValues = System.Enum.GetValues(typeof(Response));
Array itemNames = System.Enum.GetNames(typeof(Response));
for (int i = 0; i <= itemNames.Length - 1 ; i++) {
ListItem item = new ListItem(itemNames[i], itemValues[i]);
dropdownlist.Items.Add(item);
}
Use the following utility class Enumeration to get an IDictionary<int,string> (Enum value & name pair) from an Enumeration; you then bind the IDictionary to a bindable Control.
public static class Enumeration
{
public static IDictionary<int, string> GetAll<TEnum>() where TEnum: struct
{
var enumerationType = typeof (TEnum);
if (!enumerationType.IsEnum)
throw new ArgumentException("Enumeration type is expected.");
var dictionary = new Dictionary<int, string>();
foreach (int value in Enum.GetValues(enumerationType))
{
var name = Enum.GetName(enumerationType, value);
dictionary.Add(value, name);
}
return dictionary;
}
}
Example: Using the utility class to bind enumeration data to a control
ddlResponse.DataSource = Enumeration.GetAll<Response>();
ddlResponse.DataTextField = "Value";
ddlResponse.DataValueField = "Key";
ddlResponse.DataBind();
I use this for ASP.NET MVC:
Html.DropDownListFor(o => o.EnumProperty, Enum.GetValues(typeof(enumtype)).Cast<enumtype>().Select(x => new SelectListItem { Text = x.ToString(), Value = ((int)x).ToString() }))
My version is just a compressed form of the above:
foreach (Response r in Enum.GetValues(typeof(Response)))
{
ListItem item = new ListItem(Enum.GetName(typeof(Response), r), r.ToString());
DropDownList1.Items.Add(item);
}
public enum Color
{
RED,
GREEN,
BLUE
}
Every Enum type derives from System.Enum. There are two static methods that help bind data to a drop-down list control (and retrieve the value). These are Enum.GetNames and Enum.Parse. Using GetNames, you are able to bind to your drop-down list control as follows:
protected System.Web.UI.WebControls.DropDownList ddColor;
private void Page_Load(object sender, System.EventArgs e)
{
if(!IsPostBack)
{
ddColor.DataSource = Enum.GetNames(typeof(Color));
ddColor.DataBind();
}
}
Now if you want the Enum value Back on Selection ....
private void ddColor_SelectedIndexChanged(object sender, System.EventArgs e)
{
Color selectedColor = (Color)Enum.Parse(typeof(Color),ddColor.SelectedValue
}
After reading all posts I came up with a comprehensive solution to support showing enum description in dropdown list as well as selecting proper value from Model in dropdown when displaying in Edit mode:
enum:
using System.ComponentModel;
public enum CompanyType
{
[Description("")]
Null = 1,
[Description("Supplier")]
Supplier = 2,
[Description("Customer")]
Customer = 3
}
enum extension class:
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web.Mvc;
public static class EnumExtension
{
public static string ToDescription(this System.Enum value)
{
var attributes = (DescriptionAttribute[])value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
return attributes.Length > 0 ? attributes[0].Description : value.ToString();
}
public static IEnumerable<SelectListItem> ToSelectList<T>(this System.Enum enumValue)
{
return
System.Enum.GetValues(enumValue.GetType()).Cast<T>()
.Select(
x =>
new SelectListItem
{
Text = ((System.Enum)(object) x).ToDescription(),
Value = x.ToString(),
Selected = (enumValue.Equals(x))
});
}
}
Model class:
public class Company
{
public string CompanyName { get; set; }
public CompanyType Type { get; set; }
}
and View:
#Html.DropDownListFor(m => m.Type,
#Model.Type.ToSelectList<CompanyType>())
and if you are using that dropdown without binding to Model, you can use this instead:
#Html.DropDownList("type",
Enum.GetValues(typeof(CompanyType)).Cast<CompanyType>()
.Select(x => new SelectListItem {Text = x.ToDescription(), Value = x.ToString()}))
So by doing so you can expect your dropdown displays Description instead of enum values. Also when it comes to Edit, your model will be updated by dropdown selected value after posting page.
As others have already said - don't databind to an enum, unless you need to bind to different enums depending on situation. There are several ways to do this, a couple of examples below.
ObjectDataSource
A declarative way of doing it with ObjectDataSource. First, create a BusinessObject class that will return the List to bind the DropDownList to:
public class DropDownData
{
enum Responses { Yes = 1, No = 2, Maybe = 3 }
public String Text { get; set; }
public int Value { get; set; }
public List<DropDownData> GetList()
{
var items = new List<DropDownData>();
foreach (int value in Enum.GetValues(typeof(Responses)))
{
items.Add(new DropDownData
{
Text = Enum.GetName(typeof (Responses), value),
Value = value
});
}
return items;
}
}
Then add some HTML markup to the ASPX page to point to this BO class:
<asp:DropDownList ID="DropDownList1" runat="server"
DataSourceID="ObjectDataSource1" DataTextField="Text" DataValueField="Value">
</asp:DropDownList>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
SelectMethod="GetList" TypeName="DropDownData"></asp:ObjectDataSource>
This option requires no code behind.
Code Behind DataBind
To minimize the HTML in the ASPX page and do bind in Code Behind:
enum Responses { Yes = 1, No = 2, Maybe = 3 }
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
foreach (int value in Enum.GetValues(typeof(Responses)))
{
DropDownList1.Items.Add(new ListItem(Enum.GetName(typeof(Responses), value), value.ToString()));
}
}
}
Anyway, the trick is to let the Enum type methods of GetValues, GetNames etc. to do work for you.
I am not sure how to do it in ASP.NET but check out this post... it might help?
Enum.GetValues(typeof(Response));
You could use linq:
var responseTypes= Enum.GetNames(typeof(Response)).Select(x => new { text = x, value = (int)Enum.Parse(typeof(Response), x) });
DropDownList.DataSource = responseTypes;
DropDownList.DataTextField = "text";
DropDownList.DataValueField = "value";
DropDownList.DataBind();
Array itemValues = Enum.GetValues(typeof(TaskStatus));
Array itemNames = Enum.GetNames(typeof(TaskStatus));
for (int i = 0; i <= itemNames.Length; i++)
{
ListItem item = new ListItem(itemNames.GetValue(i).ToString(),
itemValues.GetValue(i).ToString());
ddlStatus.Items.Add(item);
}
public enum Color
{
RED,
GREEN,
BLUE
}
ddColor.DataSource = Enum.GetNames(typeof(Color));
ddColor.DataBind();
Generic Code Using Answer six.
public static void BindControlToEnum(DataBoundControl ControlToBind, Type type)
{
//ListControl
if (type == null)
throw new ArgumentNullException("type");
else if (ControlToBind==null )
throw new ArgumentNullException("ControlToBind");
if (!type.IsEnum)
throw new ArgumentException("Only enumeration type is expected.");
Dictionary<int, string> pairs = new Dictionary<int, string>();
foreach (int i in Enum.GetValues(type))
{
pairs.Add(i, Enum.GetName(type, i));
}
ControlToBind.DataSource = pairs;
ListControl lstControl = ControlToBind as ListControl;
if (lstControl != null)
{
lstControl.DataTextField = "Value";
lstControl.DataValueField = "Key";
}
ControlToBind.DataBind();
}
After finding this answer I came up with what I think is a better (at least more elegant) way of doing this, thought I'd come back and share it here.
Page_Load:
DropDownList1.DataSource = Enum.GetValues(typeof(Response));
DropDownList1.DataBind();
LoadValues:
Response rIn = Response.Maybe;
DropDownList1.Text = rIn.ToString();
SaveValues:
Response rOut = (Response) Enum.Parse(typeof(Response), DropDownList1.Text);
This is probably an old question.. but this is how I did mine.
Model:
public class YourEntity
{
public int ID { get; set; }
public string Name{ get; set; }
public string Description { get; set; }
public OptionType Types { get; set; }
}
public enum OptionType
{
Unknown,
Option1,
Option2,
Option3
}
Then in the View: here's how to use populate the dropdown.
#Html.EnumDropDownListFor(model => model.Types, htmlAttributes: new { #class = "form-control" })
This should populate everything in your enum list. Hope this helps..
That's not quite what you're looking for, but might help:
http://blog.jeffhandley.com/archive/2008/01/27/enum-list-dropdown-control.aspx
Why not use like this to be able pass every listControle :
public static void BindToEnum(Type enumType, ListControl lc)
{
// get the names from the enumeration
string[] names = Enum.GetNames(enumType);
// get the values from the enumeration
Array values = Enum.GetValues(enumType);
// turn it into a hash table
Hashtable ht = new Hashtable();
for (int i = 0; i < names.Length; i++)
// note the cast to integer here is important
// otherwise we'll just get the enum string back again
ht.Add(names[i], (int)values.GetValue(i));
// return the dictionary to be bound to
lc.DataSource = ht;
lc.DataTextField = "Key";
lc.DataValueField = "Value";
lc.DataBind();
}
And use is just as simple as :
BindToEnum(typeof(NewsType), DropDownList1);
BindToEnum(typeof(NewsType), CheckBoxList1);
BindToEnum(typeof(NewsType), RadoBuuttonList1);
ASP.NET has since been updated with some more functionality, and you can now use built-in enum to dropdown.
If you want to bind on the Enum itself, use this:
#Html.DropDownList("response", EnumHelper.GetSelectList(typeof(Response)))
If you're binding on an instance of Response, use this:
// Assuming Model.Response is an instance of Response
#Html.EnumDropDownListFor(m => m.Response)
In ASP.NET Core you can use the following Html helper (comes from Microsoft.AspNetCore.Mvc.Rendering):
<select asp-items="Html.GetEnumSelectList<GridReportingStatusFilters>()">
<option value=""></option>
</select>
This is my solution for Order an Enum and DataBind(Text and Value)to Dropdown using LINQ
var mylist = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().ToList<MyEnum>().OrderBy(l => l.ToString());
foreach (MyEnum item in mylist)
ddlDivisao.Items.Add(new ListItem(item.ToString(), ((int)item).ToString()));
Check out my post on creating a custom helper "ASP.NET MVC - Creating a DropDownList helper for enums": http://blogs.msdn.com/b/stuartleeks/archive/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums.aspx
If you would like to have a more user friendly description in your combo box (or other control) you can use the Description attribute with the following function:
public static object GetEnumDescriptions(Type enumType)
{
var list = new List<KeyValuePair<Enum, string>>();
foreach (Enum value in Enum.GetValues(enumType))
{
string description = value.ToString();
FieldInfo fieldInfo = value.GetType().GetField(description);
var attribute = fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false).First();
if (attribute != null)
{
description = (attribute as DescriptionAttribute).Description;
}
list.Add(new KeyValuePair<Enum, string>(value, description));
}
return list;
}
Here is an example of an enum with Description attributes applied:
enum SampleEnum
{
NormalNoSpaces,
[Description("Description With Spaces")]
DescriptionWithSpaces,
[Description("50%")]
Percent_50,
}
Then Bind to control like so...
m_Combo_Sample.DataSource = GetEnumDescriptions(typeof(SampleEnum));
m_Combo_Sample.DisplayMember = "Value";
m_Combo_Sample.ValueMember = "Key";
This way you can put whatever text you want in the drop down without it having to look like a variable name
You could also use Extension methods. For those not familar with extensions I suggest checking the VB and C# documentation.
VB Extension:
Namespace CustomExtensions
Public Module ListItemCollectionExtension
<Runtime.CompilerServices.Extension()> _
Public Sub AddEnum(Of TEnum As Structure)(items As System.Web.UI.WebControls.ListItemCollection)
Dim enumerationType As System.Type = GetType(TEnum)
Dim enumUnderType As System.Type = System.Enum.GetUnderlyingType(enumType)
If Not enumerationType.IsEnum Then Throw New ArgumentException("Enumeration type is expected.")
Dim enumTypeNames() As String = System.Enum.GetNames(enumerationType)
Dim enumTypeValues() As TEnum = System.Enum.GetValues(enumerationType)
For i = 0 To enumTypeNames.Length - 1
items.Add(New System.Web.UI.WebControls.ListItem(saveResponseTypeNames(i), TryCast(enumTypeValues(i), System.Enum).ToString("d")))
Next
End Sub
End Module
End Namespace
To use the extension:
Imports <projectName>.CustomExtensions.ListItemCollectionExtension
...
yourDropDownList.Items.AddEnum(Of EnumType)()
C# Extension:
namespace CustomExtensions
{
public static class ListItemCollectionExtension
{
public static void AddEnum<TEnum>(this System.Web.UI.WebControls.ListItemCollection items) where TEnum : struct
{
System.Type enumType = typeof(TEnum);
System.Type enumUnderType = System.Enum.GetUnderlyingType(enumType);
if (!enumType.IsEnum) throw new Exception("Enumeration type is expected.");
string[] enumTypeNames = System.Enum.GetNames(enumType);
TEnum[] enumTypeValues = (TEnum[])System.Enum.GetValues(enumType);
for (int i = 0; i < enumTypeValues.Length; i++)
{
items.add(new System.Web.UI.WebControls.ListItem(enumTypeNames[i], (enumTypeValues[i] as System.Enum).ToString("d")));
}
}
}
}
To use the extension:
using CustomExtensions.ListItemCollectionExtension;
...
yourDropDownList.Items.AddEnum<EnumType>()
If you want to set the selected item at the same time replace
items.Add(New System.Web.UI.WebControls.ListItem(saveResponseTypeNames(i), saveResponseTypeValues(i).ToString("d")))
with
Dim newListItem As System.Web.UI.WebControls.ListItem
newListItem = New System.Web.UI.WebControls.ListItem(enumTypeNames(i), Convert.ChangeType(enumTypeValues(i), enumUnderType).ToString())
newListItem.Selected = If(EqualityComparer(Of TEnum).Default.Equals(selected, saveResponseTypeValues(i)), True, False)
items.Add(newListItem)
By converting to System.Enum rather then int size and output issues are avoided. For example 0xFFFF0000 would be 4294901760 as an uint but would be -65536 as an int.
TryCast and as System.Enum are slightly faster than Convert.ChangeType(enumTypeValues[i], enumUnderType).ToString() (12:13 in my speed tests).
Both asp.net and winforms tutorial with combobox and dropdownlist:
How to use Enum with Combobox in C# WinForms and Asp.Net
hope helps
The accepted solution doesn't work, but the code below will help others looking for the shortest solution.
foreach (string value in Enum.GetNames(typeof(Response)))
ddlResponse.Items.Add(new ListItem()
{
Text = value,
Value = ((int)Enum.Parse(typeof(Response), value)).ToString()
});
You can do this a lot shorter
public enum Test
{
Test1 = 1,
Test2 = 2,
Test3 = 3
}
class Program
{
static void Main(string[] args)
{
var items = Enum.GetValues(typeof(Test));
foreach (var item in items)
{
//Gives you the names
Console.WriteLine(item);
}
foreach(var item in (Test[])items)
{
// Gives you the numbers
Console.WriteLine((int)item);
}
}
}
For those of us that want a working C# solution that works with any drop and enum...
private void LoadConsciousnessDrop()
{
string sel_val = this.drp_Consciousness.SelectedValue;
this.drp_Consciousness.Items.Clear();
string[] names = Enum.GetNames(typeof(Consciousness));
for (int i = 0; i < names.Length; i++)
this.drp_Consciousness.Items.Add(new ListItem(names[i], ((int)((Consciousness)Enum.Parse(typeof(Consciousness), names[i]))).ToString()));
this.drp_Consciousness.SelectedValue = String.IsNullOrWhiteSpace(sel_val) ? null : sel_val;
}
I realize this post is older and for Asp.net, but I wanted to provide a solution I used recently for a c# Windows Forms Project. The idea is to build a dictionary where the keys are the names of the Enumerated elements and the values are the Enumerated values. You then bind the dictionary to the combobox. See a generic function that takes a ComboBox and Enum Type as arguments.
private void BuildComboBoxFromEnum(ComboBox box, Type enumType) {
var dict = new Dictionary<string, int>();
foreach (var foo in Enum.GetValues(enumType)) {
dict.Add(foo.ToString(), (int)foo);
}
box.DropDownStyle = ComboBoxStyle.DropDownList; // Forces comboBox to ReadOnly
box.DataSource = new BindingSource(dict, null);
box.DisplayMember = "Key";
box.ValueMember = "Value";
// Register a callback that prints the Name and Value of the
// selected enum. This should be removed after initial testing.
box.SelectedIndexChanged += (o, e) => {
Console.WriteLine("{0} {1}", box.Text, box.SelectedValue);
};
}
This function can be used as follows:
BuildComboBoxFromEnum(comboBox1,typeof(Response));

Categories

Resources