populate combobox with data from enum - c#

I have enum
public enum MyEnum
{
Choice = 1,
Choicee = 2,
Choiceee = 3
}
and I want to dynamically fill list with this enum values
var data = new List<ComboBoxItem>();
where ComboBoxItem has two properties, Id and Name. Id should be enum int value and name should be enum Value like Choice or Choicee, ...

You can use Enum.GetValues for it:
var values = Enum.GetValues(typeof(SearchOption)).Cast<SearchOption>()
.Select(x => new ComboBoxItem() { Id = (int)x, Name = x.ToString() }).ToList();

Related

c# enum names to filter on in a DropDownList instead of value

I have a list of enums that includes a enumeration called Default.
public enum Fruits { Default = Banana,
Banana = 1,
Orange = 2,
Grapefruit = 3 }
I need to populate a dropdownlist that excludes the Default field.
Html.DropDownList("fruitSelector",
Enum.GetValues(typeof(Fruits)).Cast<Fruits>()
.OrderBy(o => o.GetDescription())
.Where(o => o != Fruits.Default)
.Select(o => new SelectListItem() {Text = o.GetDescription(), Value = ((int) o).ToString()}), "-- All Fruits --",
new {#class = "form-control", #aria_describedby="sizing-addon1"})
when i try to filter on Fruits.Default it removes BOTH default and the Banana. How can i do a filter comparison where i only remove Default?
[[CORRECTION]] this enum duplicates my problem. I honestly don't understand the difference.
public enum Fruits
{
Default = Peaches,
Peaches = 1,
Bananas = 2,
Grapefruit = 3,
Apple = 101,
Watermellon = 102
}
or
public enum Fruits2
{
Default = Mangos,
Mangos = 1,
Dates = 2,
Figs = 3,
Apples = 101,
Limes = 102,
Grapes = 103
}
I don't think what you're trying to do is possible as it is. The problem is your Enum structure.
public enum Fruits
{
Default = Peaches,
Peaches = 1,
Bananas = 2,
Grapefruit = 3,
Apple = 101,
Watermellon = 102
}
You're saying value of Default is Peaches of which value in turn is 1. Which essentially is the same as (B is Peaches and A is Default:
int B = 1;
int A = B;
So when we use Enum.Parse(), it treats both the same, and picks the first value. You'll understand when you look at the following scenario. Run the following code, with your current Enum:
var deflt = Enum.Parse(typeof(Fruits), Fruits.Default.ToString());
var peach = Enum.Parse(typeof(Fruits), Fruits.Peaches.ToString());
Console.WriteLine(deflt);
Console.WriteLine(peach);
The output is going to be:
Default
Default
Then change your Enum to this:
public enum Fruits
{
Peaches = Default ,
Default = 1,
Bananas = 2,
Grapefruit = 3,
Apple = 101,
Watermellon = 102
}
And run the above two lines of code again. Your output this time will be:
Peaches
Peaches
That is, Parse() picks the first defined Enum when there's an equality like you have.
EDIT:
The above explanation is slightly incorrect, as pointed out in the comments below by George Alexandria. Please see his explanation:
You have the different output when use Peaches = Default , Default = 1, and Default = Peaches, Peaches = 1, because you invoke Enum.ToString in Console.WriteLine. If you look at the var deflt, var peach you will see that they are the same in the both cases and they are the value which name is the first by alphabetical.
But there is a workaround. From your initial code sample what I gather is you need a list of Enums, their descriptions, and their numerical values, am I correct? So, I would first just grab a list of strings excluding Default which is quite simple. Then iterate through the string list, and add to a list of your SelectListItem class objects.
var res = Enum.GetNames(typeof(Fruits))
.Where(x => x != "Default");
List<SelectListItem> list = new List<SelectListItem>();
foreach (string fruit in res)
{
string desc = EnumHelper<Fruits>.GetEnumDescription(fruit); // This is a utility method I use. You can get the description using your extension method.
int val = (int)Enum.Parse(typeof(Fruits), fruit);
list.Add(new SelectListItem { enumName = fruit, enumDesc = desc, enumVal = val });
}
And if you must have that OrderBy, after creating your SelectListItem list, sort it once again by Description.
You should compare enum values by their names, because Default and Banana are equal. So just try to retrieve names, filter them and parse them to values.
var res = Enum.GetNames(typeof(Fruits))
.Where(o => o != nameof(Fruits.Default))
.Select(o => Enum.Parse(typeof(Fruits), o))
.Cast<Fruits>().ToList();
It's your full example:
Html.DropDownList("fruitSelector",
Enum.GetNames(typeof(Fruits))
.Where(o => o != nameof(Fruits.Default))
.Select(o => Enum.Parse(typeof(Fruits), o)).Cast<Fruits>()
.OrderBy(o => o.GetDescription())
.Select(o => new SelectListItem() { Text = o.GetDescription(), Value = ((int)o).ToString() }), "-- All Fruits --",
new { #class = "form-control", #aria_describedby = "sizing-addon1" })

Add duplicates together in List

First question :)
I have a List<Materiau> (where Materiau implements IComparable<Materiau>), and I would like to remove all duplicates and add them together
(if two Materiau is the same (using the comparator), merge it to the first and remove the second from the list)
A Materiau contains an ID and a quantity, when I merge two Materiau using += or +, it keeps the same ID, and the quantity is added
I cannot control the input of the list.
I would like something like this:
List<Materiau> materiaux = getList().mergeDuplicates();
Thank you for your time :)
Check out Linq! Specifically the GroupBy method.
I don't know how familiar you are with sql, but Linq lets you query collections similarly to how sql works.
It's a bit in depth to explain of you are totally unfamiliar, but Code Project has a wonderful example
To sum it up:
Imagine we have this
List<Product> prodList = new List<Product>
{
new Product
{
ID = 1,
Quantity = 1
},
new Product
{
ID = 2,
Quantity = 2
},
new Product
{
ID = 3,
Quantity = 7
},
new Product
{
ID = 4,
Quantity = 3
}
};
and we wanted to group all the duplicate products, and sum their quantities.
We can do this:
var groupedProducts = prodList.GroupBy(item => item.ID)
and then select the values out of the grouping, with the aggregates as needed
var results = groupedProducts.Select( i => new Product
{
ID = i.Key, // this is what we Grouped By above
Quantity = i.Sum(prod => prod.Quantity) // we want to sum up all the quantities in this grouping
});
and boom! we have a list of aggregated products
Lets say you have a class
class Foo
{
public int Id { get; set; }
public int Value { get; set; }
}
and a bunch of them inside a list
var foocollection = new List<Foo> {
new Foo { Id = 1, Value = 1, },
new Foo { Id = 2, Value = 1, },
new Foo { Id = 2, Value = 1, },
};
then you can group them and build the aggregate on each group
var foogrouped = foocollection
.GroupBy( f => f.Id )
.Select( g => new Foo { Id = g.Key, Value = g.Aggregate( 0, ( a, f ) => a + f.Value ) } )
.ToList();
List<Materiau> distinctList = getList().Distinct(EqualityComparer<Materiau>.Default).ToList();

winform - setting Selected value of listbox

I had a list box called listbox1 will bounded to list like this:
ValueVM word1 = new ValueVM { Id = 1, Name = "AAA" };
ValueVM word2 = new ValueVM { Id = 2, Name = "XBB" };
ValueVM word3 = new ValueVM { Id = 3, Name = "ACC" };
ValueVM word4 = new ValueVM { Id = 4, Name = "ACB" };
ValueVM word5 = new ValueVM { Id = 5, Name = "OTD" };
ValueVM word6 = new ValueVM { Id = 6, Name = "FDD" };
var li = new List<ValueVM>() { word1, word2, word3, word4, word5, word6 };
listBox1.DataSource = li.OrderBy(l=>l.Name).ToList();
listBox1.DisplayMember = "Name";
listBox1.ValueMember = "Id";
I want to one Item to be seleted in this list box, suppose I want the Id=2;
int myID = 2;
//Idont know what the selected index will be but I need the selected value to be set
// I tried to set listBox1.SelectedValue=myId.ToString();
//but still returning null
listBox1.SelectedValue = myID;
as mentioned in MSDN:
Gets or sets the value of the member property specified by the ValueMember property. (Inherited from ListControl.)
my problem that seleted value get the value from value member but it didn't set the value?
any Ideas?
You're in the right direction only. SelectedValue should do what you need.
listBox1.SelectedValue = 2;//this works for me
Note: You've to set the int here since datasource is int. setting "2" won't work
Try with
listBox1.SetSelected(MyId, true);
Take a look at this
you should change yourcode into someting like this
listBox1.DataSource = li.OrderBy(l=>l.Name).ToArray();
because the datasource does not understand IOrderedEnumerable
Hopethis help

Select multiple fields group by and sum

I want to do a query with linq (list of objects) and I really don't know how to do it, I can do the group and the sum but can't select rest of the fields.
Example:
ID Value Name Category
1 5 Name1 Category1
1 7 Name1 Category1
2 1 Name2 Category2
3 6 Name3 Category3
3 2 Name3 Category3
I want to group by ID, SUM by Value and return all fields like this.
ID Value Name Category
1 12 Name1 Category1
2 1 Name2 Category2
3 8 Name3 Category3
Updated :
If you're trying to avoid grouping for all the fields, you can group just by Id:
data.GroupBy(d => d.Id)
.Select(
g => new
{
Key = g.Key,
Value = g.Sum(s => s.Value),
Name = g.First().Name,
Category = g.First().Category
});
But this code assumes that for each Id, the same Name and Category apply. If so, you should consider normalizing as #Aron suggests. It would imply keeping Id and Value in one class and moving Name, Category (and whichever other fields would be the same for the same Id) to another class, while also having the Id for reference. The normalization process reduces data redundancy and dependency.
void Main()
{
//Me being lazy in init
var foos = new []
{
new Foo { Id = 1, Value = 5},
new Foo { Id = 1, Value = 7},
new Foo { Id = 2, Value = 1},
new Foo { Id = 3, Value = 6},
new Foo { Id = 3, Value = 2},
};
foreach(var x in foos)
{
x.Name = "Name" + x.Id;
x.Category = "Category" + x.Id;
}
//end init.
var result = from x in foos
group x.Value by new { x.Id, x.Name, x.Category}
into g
select new { g.Key.Id, g.Key.Name, g.Key.Category, Value = g.Sum()};
Console.WriteLine(result);
}
// Define other methods and classes here
public class Foo
{
public int Id {get;set;}
public int Value {get;set;}
public string Name {get;set;}
public string Category {get;set;}
}
If your class is really long and you don't want to copy all the stuff, you can try something like this:
l.GroupBy(x => x.id).
Select(x => {
var ret = x.First();
ret.value = x.Sum(xt => xt.value);
return ret;
}).ToList();
With great power great responsibility comes. You need to be careful. Line ret.value = x.Sum(xt => xt.value) will change your original collection, as you are passing reference, not new object. If you want to avoid it, you need to add some Clone method into your class like MemberwiseClone (but again, this will create shallow copy, so be careful). Afer that just replace the line with: var ret = x.First().Clone();
try this:
var objList = new List<SampleObject>();
objList.Add(new SampleObject() { ID = 1, Value = 5, Name = "Name1", Category = "Catergory1"});
objList.Add(new SampleObject() { ID = 1, Value = 7, Name = "Name1", Category = "Catergory1"});
objList.Add(new SampleObject() { ID = 2, Value = 1, Name = "Name2", Category = "Catergory2"});
objList.Add(new SampleObject() { ID = 3, Value = 6, Name = "Name3", Category = "Catergory3"});
objList.Add(new SampleObject() { ID = 3, Value = 2, Name = "Name3", Category = "Catergory3"});
var newList = from val in objList
group val by new { val.ID, val.Name, val.Category } into grouped
select new SampleObject() { ID = grouped.ID, Value = grouped.Sum(), Name = grouped.Name, Category = grouped.Category };
to check with LINQPad:
newList.Dump();

C# Linq List Compare and update lists

I have 2 lists containing different types. One is a string[] and another is a List<SelectListItem>.
SelectListItem (it's in mvc):
public string Text {get;set;}
public string Value {get;set;}
public bool Selected {get;set;}
My string[] is just contains some text values.
What i'm trying to do is, get whatever is in the string[], then set "Selected = true" for whatever Value matches, and "Selected = false" for what doesnt match.
So lets say my string[] is:
Test1
Test2
Test3
And my List<SelectListItem> is:
new SelectListItem { Text = "Testing", Value = "Test1", Selected = false },
new SelectListItem { Text = "Testing", Value = "Test4", Selected = true }
In the above List<SelectListItem>, i have one match. So what i'd like to do, is set Selected = true for that particular entry so that i end up with:
new SelectListItem { Text = "Testing", Value = "Test1", Selected = true },
new SelectListItem { Text = "Testing", Value = "Test4", Selected = false }
How would I achieve this?
foreach(var i in selectListItemList)
i.Selected = stringArray.Contains(i.Value);
or using List.ForEach:
selectListItemList.ForEach(i => i.Selected = stringArray.Contains(i.Value));
How about
list.ForEach(x => x.Selected = stringarray.Contains(x.Value))
var items = SelectListItems.Where(p=>stringArray.Contains(p));;
foreach(var item in items)
item.Selected=true;

Categories