SelectList with SelectListGroup - c#

I'm trying to return a SelectList with <optgroup>'s using SelectListGroup, but the code below only returns the values in the SelectList without the groups. How can I have my select list separated by groups?
public SelectList MyList()
{
var group1 = new SelectListGroup() { Name = "Group 1" };
var group2 = new SelectListGroup() { Name = "Group 2" };
var items = new List<SelectListItem>();
items.Add(new SelectListItem() { Value = "1", Text = "Item 1", Group = group1 });
items.Add(new SelectListItem() { Value = "2", Text = "Item 2", Group = group2 });
return new SelectList(items, "Value", "Text");
}

I find this method works, which uses a strongly-typed approach:
View model:
public class PageViewModel
{
public int SelectedDropdownItem { get; set; }
public IEnumerable<SelectListItem> DropdownList { get; set; }
}
Example entity model (for this example):
public class Entity
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public bool IsDefault { get; set; }
}
Controller:
// Get list for the dropdown (this uses db values)
var entityList = db.Entity.ToList();
// Define the Groups
var group1 = new SelectListGroup { Name = "Active" };
var group2 = new SelectListGroup { Name = "Allowed" };
// Note - the -1 is needed at the end of this - pre-selected value is determined further down
// Note .OrderBy() determines the order in which the groups are displayed in the dropdown
var dropdownList = new SelectList(entityList.Select(item => new SelectListItem
{
Text = item.Name,
Value = item.Id,
// Assign the Group to the item by some appropriate selection method
Group = item.IsActive ? group1 : group2
}).OrderBy(a => a.Group.Name).ToList(), "Value", "Text", "Group.Name", -1);
// Assign values to ViewModel
var viewModel = new PageViewModel
{
// Assign the pre-selected dropdown value by appropriate selction method (if needed)
SelectedDropdownItem = entityList.FirstOrDefault(a => a.IsDefault).Id,
DropdownList = dropdownList
};
View:
<!-- If needed, change 'null' to "Please select item" -->
#Html.DropDownListFor(a => a.SelectedDropdownItem, Model.DropdownList, null, new { #class = "some-class" })
Hope it helps someone.

Related

How to select value from selectlist?

How to select a text from selectlist? I want to auto select name "Dave" name from back-end on line First_Name_SELECT = "Dave";
<select asp-for="Person.First_Name" asp-items="#Model.First_Name_SELECT">
</select>
[BindProperty(SupportsGet = true)]
public string? First_Name { get; set; }
public SelectList? First_Name_SELECT { get; set; }
First_Name_SELECT = new SelectList(await _services.Get_Names());
First_Name_SELECT = "Dave";
public async Task<List<string>> Get_Names()
{
IQueryable<string> Query = (from m in _context2.Names_DbSet
select m.First_Names).Distinct().OrderBy(m => m);
return await Query.ToListAsync();
}
** UPDATE ** Following code works fine below but why First_Name_SELECT doesn't work? is this becuase I am using IQueryable?
[BindProperty(SupportsGet = true)]
public string? Last_Name { get; set; }
public SelectList? Last_Name_SELECT { get; set; }
Last_Name_SELECT = new SelectList(await _services.Get_LastNames());
var testing = Last_Name_SELECT .Where(x => x.Value.Contains("Name8")).FirstOrDefault();
testing.Selected = true;
public List<SelectListItem> Get_LastNames()
{
List<SelectListItem> Query = new List<SelectListItem>
{
new SelectListItem() { Selected =true, Value = "name1", Text = "name1" },
new SelectListItem() { Value = "name2", Text = "name2" },
new SelectListItem() { Value = "name3", Text = "name3" },
new SelectListItem() { Value = "name4", Text = "name4" },
new SelectListItem() { Value = "name5", Text = "name5" },
new SelectListItem() { Value = "name6", Text = "name6" },
new SelectListItem() { Value = "name7", Text = "name7" },
new SelectListItem() { Value = "name8", Text = "name8" },
new SelectListItem() { Value = "name9", Text = "name9" }
};
return Query;
}
If you have a model Person, you can try the below code:
var First_Name_SELECTSelectedValue = "Dave";
First_Name_SELECT = new SelectList(await _services.Get_Names(), First_Name_SELECTSelectedValue);
result:
You can read SelectList(IEnumerable, Object) to know more.
public SelectList (System.Collections.IEnumerable items, object
selectedValue);

Cannot group data in LINQ

I have a question about a LINQ grouping.
I thought that grouping would be a simple matter of using the GroupBy function on the result set and specifying what to group it by. However my items appear to not be grouping together and instead are displaying as if the GroupBy function wasn't there. I want to group by the itemPk, but I'm can't seem to do it. I have tried grouping by both category.ItemFk and Item.Itempk, but no luck. Could someone give me a pointer on this?
var itemIds = items.Select(i => i.ItemId).ToList();
var itemAndCatJoin =
from item in Context.SCS_Items
join category in Context.SCS_ItemCategories
on item.ItemPk equals category.ItemFk
into temp
from category in temp.DefaultIfEmpty()
select new ExportItemTable
{
Category = category,
Item = item
};
return itemAndCatJoin.Where(i => itemIds.Contains(i.Item.ItemPk))
.GroupBy(n => new {n.Item, n.Category})
.Select(i => new ExportableItem
{
ItemPk = i.Key.Item.ItemPk,
Name = i.Key.Item.Name,
Description = i.Key.Item.Description,
Price = i.Key.Item.Price,
Category = i.Key.Category.Category.Category_Name,
GLDepartment = i.Key.Category.GL_Department.Name ?? "",
GLName = i.Key.Category.GL_Name.Name ?? "",
StartDate = i.Key.Item.StartDate,
EndDate = i.Key.Item.EndDate,
FiscalYear = i.Key.Item.SCS_FiscalYear.Name,
School = i.Key.Item.School != null ? i.Key.Item.School.School_Name : i.Key.Item.Board.Board_Name,
Beneficiary = i.Key.Item.SCS_Beneficiary.Name,
Quantity = i.Key.Item.MaxQuantity,
Deleted = i.Key.Item.DeletedFlag,
OptionalStudents = i.Key.Item.SCS_Attachments.Where(a => !a.IsRequired).SelectMany(a => a.SCS_StudentAttachments).Where(s => !s.DeletedFlag).Select(s => s.StudentFk).Distinct().Count(),
RequiredStudents = i.Key.Item.SCS_Attachments.Where(a => a.IsRequired).SelectMany(a => a.SCS_StudentAttachments).Where(s => !s.DeletedFlag).Select(s => s.StudentFk).Distinct().Count(),
IsPublic = i.Key.Item.IsPublic,
AllowRecurring = i.Key.Item.AllowRecurringPayments,
EffectiveCutoff = i.Key.Item.SCS_Attachments.Where(a => !a.DeletedFlag && a.CourseDropCutoff.HasValue).Select(a => a.CourseDropCutoff).OrderBy(a => a).FirstOrDefault(),
CreatedDate = i.Key.Item.CreatedDate
}).OrderBy(i => i.ItemPk).ToList();
}
your groupbyy is indeed doing nothing for you, you need to tell the groupby what to group by....
like
.GroupBy(n => n.Category)
Here is a simple example to your grouping question:
class Program
{
static void Main()
{
var allItems = GetAllItems();
var groups = from item in allItems
group item by item.Category
into newGroup
select newGroup;
foreach (var group in groups)
{
Console.WriteLine($"\nCategory: {group.Key}");
foreach (var item in group)
{
Console.WriteLine($"{item.Name}: {item.Price}");
}
}
Console.ReadLine();
}
static List<Category> GetAllCategories()
{
return new List<Category>()
{
new Category() { Id = 1, Name = "Programming Books" },
new Category() { Id = 2, Name = "Fiction Books" }
};
}
static List<Item> GetAllItems()
{
return new List<Item>()
{
new Item() { Id = 1, Name = "Embedded Linux", Category = 1, Price = 9.9 },
new Item() { Id = 2, Name = "LINQ In Action", Category = 1, Price = 36.19 },
new Item() { Id = 3, Name = "C# 6.0 and the .NET 4.6 Framework", Category = 1, Price = 40.99 },
new Item() { Id = 4, Name = "Thinking in LINQ", Category = 1, Price = 36.99 },
new Item() { Id = 5, Name = "The Book Thief", Category = 2, Price = 7.99 },
new Item() { Id = 6, Name = "All the Light We Cannot See", Category = 2, Price = 16.99 },
new Item() { Id = 7, Name = "The Life We Bury", Category = 2, Price = 8.96 }
};
}
}
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public int Category { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
}
This example is simple enough for anyone new to LINQ. I am sure you can make some adjustment to make it work for your specific issue. Hope this will help.

Using Linq to drill down on strongly typed objects

I have been reading tutorials on Linq and Lambda expressions all afternoon. I'll get it eventually and it won't take me that long, but maybe someone can show me an example of how to do what I'm trying for and I'll grasp it quicker.
I have a client side jQuery script that calls a routine in my Controller that returns a JsonResult.
Given ViewModels of:
public class Country
{
[Key]
public int Id { get; set; }
[Index("UX_Country_CountryCode", IsUnique = true)]
[MaxLength(5)]
public string CountryCode { get; set; }
public string CountryName { get; set; }
public virtual ICollection<State> States { get; set; }
}
public class State
{
[Key]
public int Id { get; set; }
[Index("UX_State_StateCodeCountryId", IsUnique = true, Order = 1)]
[MaxLength(5)]
public string StateCode { get; set; }
public string StateName { get; set; }
[ForeignKey("Country")]
[Index("UX_State_StateCodeCountryId", IsUnique = true, Order = 0)]
public int CountryId { get; set; }
public virtual Country Country { get; set; }
}
Example data:
new Country { Id = 1, CountryCode = "USA", CountryName = "United States" };
new Country { Id = 2, CountryCode = "CAN", CountryName = "Canada" };
new State { Id = 1, StateCode = "FL", StateName = "Florida", CountryId = 1 };
new State { Id = 2, StateCode = "CA", StateName = "California", CountryId = 1 };
new State { Id = 3, StateCode = "IA", StateName = "Iowa", CountryId = 1 };
Call the following with a URI of /Controller/StateList/USA
[AllowAnonymous]
[AcceptVerbs(HttpVerbs.Get)]
public JsonResult StateList(string Id)
{
// I need to know the Id of CountryCode == "USA"
// Get <Country> with CountryCode == "USA". (I think this works)
IEnumerable<SelectListItem> country = from c in GetCountryList()
where c.Value == Id
select c;
// Now get all states where <State>.CountryId == country.Id
var state = from State s in dbLocations.States
where s.CountryId == country.id
select s;
return Json(new SelectList(state.ToArray(), "StateCode", "StateName"), JsonRequestBehavior.AllowGet);
}
public IEnumerable<SelectListItem> GetCountryList()
{
var countries = new SelectList(dbLocations.Countries, "CountryCode", "CountryName").ToList();
countries.Insert(0, (new SelectListItem { Text = "Select Country", Value = "-1" }));
countries.Insert(1, (new SelectListItem { Text = "United Sates", Value = "USA" }));
countries.Insert(2, (new SelectListItem { Text = "Canada", Value = "CAN" }));
countries.Insert(3, (new SelectListItem { Text = "Mexico", Value = "MEX" }));
countries.Insert(4, (new SelectListItem { Text = "Brazil", Value = "BRA" }));
countries.Insert(5, (new SelectListItem { Text = "------------------------", Value = "-1" }));
IEnumerable<SelectListItem> countrylist =
countries.Select(m => new SelectListItem()
{
Text = m.Text,
Value = m.Value
});
return countrylist;
}
I've made several attempts at the StateList() code and just not grasping how to do this using Linq. I think GetCountryList() is ok - I use it many times elsewhere in the app. How would StateList() best be coded?
Also, I've found some Linq tutorials, but they're not clicking. Anyone know of a good one?
The simplest way would be to access dbLocations and fetch the country from the database directly.
[AllowAnonymous]
[AcceptVerbs(HttpVerbs.Get)]
public JsonResult StateList(string Id)
{
// Get the country by Country Code
var country = dbLocations.Countries.FirstOrDefault(c => c.CountryCode == Id);
// Get all states where countryId equals the Id from the action
var states = from State s in dbLocations.States
where s.CountryId == country.Id
select s;
return Json(new SelectList(states.ToArray(), "StateCode", "StateName"), JsonRequestBehavior.AllowGet);
}
EDIT: You may think of switching the Value of SelectedListItem to the Country.Id instead of Country.CountryCode the value is not seen in the UI anyway. This way it would be easier to access the country by its Id instead of CountryCode

Bind Dropdown using mvc4

I need help to bind drop-down values from models.
Model.cs
public class BloodGroup
{
public BloodGroup()
{
ActionsList = new List<SelectListItem>();
}
[Display(Name="Blood Group")]
public int Group { get; set; }
public IEnumerable<SelectListItem> ActionsList { get; set; }
}
public class ActionType
{
public int GroupId { get; set; }
public string BloodGroup { get; set; }
}
In the Controller:
List<ActionType> actionType = GetCourses();
bGroup.ActionsList = from action in actionType
select new SelectListItem
{
Text = action.BloodGroup,
Value = ((int)action.GroupId).ToString(),
Selected = action.BloodGroup.Equals("A+")?true:false
};
return view;
public List<ActionType> GetCourses()
{
return new List<ActionType> {
new ActionType () { GroupId = 1, BloodGroup = "A+"},
new ActionType () { GroupId = 2, BloodGroup = "B+"},
new ActionType () { GroupId = 3, BloodGroup = "O+" },
new ActionType () { GroupId = 4, BloodGroup = "AB+" },
new ActionType () { GroupId = 5, BloodGroup = "A-"},
new ActionType () { GroupId = 6, BloodGroup = "B-"},
new ActionType () { GroupId = 7, BloodGroup = "O-" },
new ActionType () { GroupId = 8, BloodGroup = "AB-" }
};
}
It successfully return to view. But in view when bind dropdown it throws an error.
in view
#model MyMVC.Models.BloodGroup
#Html.DropDownListFor(m => m.Group, new SelectList(Model.ActionsList, "Value", "Text",true), "-- Select --")</li>
It returns error.
Object reference not set to an instance of an object.
Model.ActionsList is set a Null.
I don't know why it shows null, though I inherit the model.
I need help on how to bind the SelectList value to dropdown
You need to pass a instance of BloodGroup class to the view in your action method, like below:
public ActionResult YourAction()
{
List<ActionType> actionType = GetCourses();
var model = new BloodGroup()
{
ActionsList = (from action in actionType
select new SelectListItem
{
Text = action.BloodGroup,
Value = ((int) action.GroupId).ToString(),
Selected = action.BloodGroup.Equals("A+")
})
};
return View(model);
}
Then in your view:
#model BloodGroup
#Html.DropDownListFor(m => m.Group, Model.ActionsList,"-- Select --")
Notice
Using above example it'll show you the view without errors, but the selected item in your downdownList will NOT show correctly. For showing the selected item correctly, you need to change the type of Grop property to String, like below:
public class BloodGroup
{
//
[Display(Name = "Blood Group")]
public string Group { get; set; }
//
}
Then use above same action method, make your view like:
#model BloodGroup
#Html.DropDownList("Group", Model.ActionsList, "-- Select --")

Sort list by eventually existing value

I have to sort a given list by a value which may or may not be given inside another list of each element. If no value is given, this element should appear at the bottom of the sorted list.
Here's a short example: I want to sort the list Items based on the Value of the Property which has the name foo
public class Item {
public string Name { get; set; }
public List<Property> Properties { get; set; }
}
public class Property {
public string Name { get; set; }
public int Value { get; set; }
}
List<Item> items = new List<Item>() {
new Item() {
Name = "Item 1",
Properties = new List<Property>() {
new Property {
Name = "foo",
Value = 5
},
new Property {
Name = "bar",
Value = 7
}
}
},
new Item() {
Name = "Item 2",
Properties = new List<Property>() {
new Property {
Name = "bar",
Value = 2
}
}
},
new Item() {
Name = "Item 3",
Properties = new List<Property>() {
new Property {
Name = "foo",
Value = 1
}
}
}
The sorted list should contain the Items in the order Item 1, Item 3, Item 2
I tried this:
items.FetchOrderBy
(
x => x.Properties
.FirstOrDefault
(
y => y.Name = "foo"
)
.Value
)
.ToList();
...But got the following exception: Antlr.Runtime.NoViableAltException
The problem is that when there's no property match, FirstOrDefault returns null. You could get around this by using a null-coalescing operator:
items.FetchOrderBy
(
x => (x.Properties
.FirstOrDefault
(
y => y.Name == "foo"
)
// Send non-matches to the bottom
?? new Property { Value = Int32.MaxValue })
.Value
)
.ToList();

Categories