Populating Dropdown using Reflection - c#

I am using MVC4 and what I want to do is use a dropdown connected to my search box to search for the selected property. How would I am stuck on the Text= prop.Name. How could I go through and access all of the properties using this.
My Controller
public ActionResult SearchIndex(string searchString)
{
var selectListItems = new List<SelectListItem>();
var first = db.BloodStored.First();
foreach(var item in first.GetType().GetProperties())
{
selectListItems.Add(new SelectListItem(){ Text = item.Name, Value = selectListItems.Count.ToString()});
}
IEnumerable<SelectListItem> enumSelectList = selectListItems;
ViewBag.SearchFields = enumSelectList;
var bloodSearch = from m in db.BloodStored
select m;
if (!String.IsNullOrEmpty(searchString))
{
bloodSearch = bloodSearch.Where(s => string.Compare(GetValue(s, propertyName), searchString) == 0);
}
return View(bloodSearch);
}
The selectlist is working now I just need to go over my searchstring and how to pass two parameters now.

I'm not quite sure what you're asking. If you want to create a list of objects with the property Text set to the property name of the object, you could get the first object in the BloodStored enumerable and create a list of anonymous types:
// Get one instance and then iterate all the properties
var selectListItems = new List<object>();
var first = db.BloodStore.First();
foreach(var item in first.GetType().GetProperties()){
selectListItems.Add(new (){ Text = item.Name});
}
ViewBag.SearchFields = selectListItems;

Related

Modify text in items in SelectList

I can't find a way to modify the text in each item on a SelectList to populate a dropdown menu. The values I'm populating the list with are from a database and are encrypted. I want to decrypt each item as it is loaded into the list and replace the encrypted text with the decrypted one.
This is an example of what I thought would work, But I still get the same results in the dropdown menu.
public ActionResult Create()
{
SelectList Types = new SelectList(db.Room_Type, "ID_Room_Type", "Name");
foreach(SelectListItem i in Types)
{
i.Text = Util.Crypt.Decrypt(i.Text);
}
ViewBag.Room_Type = Types;
return View();
}
Is there any permanent way to change and process this text as is being loaded?
I think this should work:
var l = new List<SelectListItem>();
foreach(var i in db.Room_Type)
{
var sli = new SelectListItem();
sli.Value = i.ID_Room_Type;
sli.Text = Util.Crypt.Decrypt(i.Name);
l.Add(sli);
}
SelectList Types = new SelectList(l);

Invalid Operation Exception passing to View

I am trying, to no avail to display a dropdown list of all units a user doesnt already have. So i have List A with all Units and List B with all Units the user has. What i want is List C which is basically List A with List B removed from it. I have so far managed to filter out the data but i cant seem to display it in my View. All i get is a blank dropdown list. Can anyone see where im going wrong??
public ActionResult AddUnit(String usrCode)
{
var units = unitsClient.GetAllunits();
var allunitsCode = (from s in units select s.unitCode).ToList();
var thisUnitCode = (from s in db.Units
where s.UsrCode == usrCode
select s.UnitCode).ToList();
var notGot = allunitsCode.Except(thisUnitCode);
List<unitsummaryDTO> list = UnitList(units, notGot);
ViewBag.unitCode = new SelectList(list, "unitCode", "unitTitle");
var model = new UserUnit { UsrCode = usrCode };
return View("AddUnit", model);
}
private List<unitsummaryDTO> UnitList(unitsService.unitsDTO[] units, IEnumerable<string> notGot)
{
var allunits = unitsClient.GetAllunits();
var allunitsCode = (from s in allunits select s.unitCode).ToList();
IEnumerable<String> list1 = allunitsCode;
IEnumerable<String> list2 = notGot;
var listFinal = list1.Union(list2).toList;
return listFinal.Select(x => new unitsummaryDTO(){unitCode = x}).ToList();
}
This is my View model. But all i get is a blank drop down?? Can anyone help me out.
#model Projv1.UserUnit
#Html.HiddenFor(model => model.unitCode)
#Html.DropDownList("UnitCode")
It would be blank because #Html.DropDownList("UnitCode") doesn't have a source. If you look at MSDN for Html.DropDownList, the one your most likely trying to use is DropDownList(String, IEnumerable<SelectListItem>).
Your putting your select list into the ViewBag as unitCode so try:
#Html.DropDownList("Unit Code", ViewBag.unitCode);
A much easier way of handling this is to extend UserUnit as a ViewModel (or create something) to have the items needed by the SelectList on it and let MVC do the heavy lifting in the binding.
public class UserUnit
{
// ... other properties
IEnumerable<unitsummaryDTO> UnitCodes { get; set; }
public string MyUnitCode { get; set; }
}
Then
#Html.DropDownListFor(n => n.MyUnitCode,
new SelectList(Model.UnitCodes, "unitCode", "unitTitle"))

How to add one List into another List

I am trying to add one list into another but it is giving me error of The best overloaded method match for 'System.Collection.Generic.List.AddRange(System.Collections.Generic.IEnumerable)' has some invalid arguments
My code is:
public ActionResult RegisteredEvent(string Cno)
{
if (Request.IsAjaxRequest())
{
List<tblEvent> eventlist = new List<tblEvent>();
List<RegisteredEvent> list = new List<RegisteredEvent>();
var db = new clubDataContext();
int[] eventIds = (from m in db.EventRegistrations where m.Cno == Cno select m.Event_Id).ToArray();
int i = 1;
foreach (var item in eventIds)
{
list = (from m in db.tblEvents
where item.Equals(m.EventId)
select new RegisteredEvent()
{
id = m.EventId,
caption = m.Caption,
description = m.Description,
date = m.Date.ToString()
}).ToList();
eventlist.AddRange(list); //Here I am getting error
}
ViewBag.eventDetail = eventlist;
return PartialView("RegisteredEvent");
Simply speaking, you can only concatenate lists of the same type.¹
eventlist is a List<tblEvent>
list is a List<RegisteredEvent>
¹ This is not entirely correct: Since IEnumerable is covariant, it is actually possible to add entries of a List<S> to a List<T>, if S is a subtype of T.
The T in List<T> needs to have the same type or inherent from the same base type
List<RegisteredEvent> eventlist
List<RegisteredEvent> list
or
List<tblEvent> eventlist
List<tblEvent> list
You can use IEnumerable.Select as this (I don't know the structure of tblEvent, so adapt this at your code.
eventlist.AddRange(list.Select(x => new tblEvent{ id = x.id, caption = x.caption, ... }));
But the best way is to create directly a tblEvent
//the list sent to View
eventlist = (from m in db.tblEvents
where item.Equals(m.EventId)
select new tblEvent() //here
{
id = m.EventId,
caption = m.Caption,
description = m.Description,
date = m.Date.ToString()
}).ToList();

SelectList Not Coming Back Sorted - C# MVC 3

All,
I am trying to sort my selectlist items and then prepend a default list item to the list, something like "Select an Item Below" and return that list via a method. I noticed that the list is not being sorted because it looks like, from what ReSharper is saying, I need to return the sorted result - so my method is not returning a sorted list.
Is there a way to do the sorting and prepending in the method?
Here is what I have:
public static IEnumerable<SelectListItem> GetBuildingClubs(List<BuildingClub> localClubs, List<BuildingClub> psfyClubs)
{
var buildingClubList = new List<SelectListItem>();
IEnumerable<BuildingClub> allBuildingClubs = localClubs.Union(psfyClubs);
foreach (BuildingClub b in allBuildingClubs)
{
buildingClubList.Add(new SelectListItem
{
Value = b.MasterCustomerId,
Text = b.NewBuildingClubName
});
}
//Sort list
buildingClubList.OrderBy(c => c.Text);
//Prepend to sorted list
buildingClubList.Insert(0, new SelectListItem
{
Value = "",
Text = "Select an Item Below"
});
return buildingClubList;
}
OrderBy doesn't modify the input list; it returns a new sorted sequence. You need to store that sequence and use it to build your list:
buildingClubList = buildingClubList.OrderBy(c => c.Text).ToList();
Alternatively, sort the items before you add them to the list:
IEnumerable<BuildingClub> allBuildingClubs = localClubs.Union(psfyClubs).OrderBy(b => b.NewBuildingClubName);

Checking List Item Id

Currently I am trying to check a selected Item Id and display in dropdown list on an Edit page which will show the previous selected item. The Items show based on their active status. All active items are displayed in the dropdown and if the previous selection choice for the user is currently inactive, it should still default to that item in the dropdown list since it was the selection previously made. My issue is that i am not able to show the inactive item that was selected by the user on the edit page. I will post all my code and this is a continuation of a question asked in a different link: passing null parameters
my Code in CONTROLLER:
private IEnumerable<SearchItems> GetItems(ItemDescriptionFormViewModel viewModel = null)
{
if(viewModel == null)
viewModel = new AppointmentViewModel();
IOrderedQueryable<ItemDescription> items= _itemDescriptionRepository.FindAll().OrderBy(
c => c.Sort == null).ThenBy(
c => c.Sort).ThenBy(c => c.Description);
if(items.Count()==0)
ModelState.AddModelError("", string.Format("No active {0} entered.", Kids.Resources.Entities.ItemDescription.EntityNamePlural));
return
_itemDescriptionRepository.FindAll().OrderBy(c => c.Description).Where(a=>a.IsActive == true || a.ItemDescriptionId == viewModel.ItemDescriptionId).Select(
c => new SearchItems {Text = c.Description, Value = c.ItemDescriptionId.ToString()});
}
My Edit Method in CONTROLLER:
[HttpGet]
[AppointmentAuthorization]
public ActionResult Edit(Guid appointmentId)
{
Appointment appointment = _appointmentService.Get(appointmentId);
if (appointment == null) return View("NotFound");
var viewModel = new AppointmentViewModel
{
AppointmentId = appointment.AppointmentId,
};
viewModel.Items= GetItems();
return this.RazorView("Edit", viewModel);
}
It seems like something is missing and passing viewModel as a parameter in viewModel.Items= GetItems() didn't do much. I also have another Post method for Edit and a Create method all which call the GetItems() method. Any help will be great. Thanks :D
This is what i have in my ViewModel class:
public IEnumberable<SearchItems> Items {get; set;}
public Guid ItemDescriptionid {get; set;}
Create Method:
[HttpGet]
[AppointmentAuthorization]
public ActionResult Create(Guid caseId)
{
var viewModel = new AppointmentViewModel
{
Items= GetItems()
};
return this.RazorView("Create", viewModel);
}
*****SOLUTION*****
private IEnumerable<SearchItems> GetItems(Appointment appointment)
{
IEnumerable<short?> itemDescriptionIds =
appointment.AppointmentItems.Where(c => c.ItemDescriptionId.HasValue).Select(
c => c.ItemDescriptionId).Distinct();
IOrderedQueryable<ItemDescription> itemDescription =
_itemDescriptionRepository.FindAll().Where(
a => a.IsActive == true || itemDescriptionIds.Contains(a.ItemDescriptionId)).OrderBy(
d => d.Description);
return itemDescription.Select(c=> new SearchItems{Text = c.Description, Value = c.ItemDescriptionId.ToString()});
}
The reason your inital code wasn't querying the previously selected value was because your query a.ItemDescriptionId == viewModel.ItemDescriptionId, compares item description id, but in your View Model you only set appointment id. If you need item description id then make sure you initialize it.
var viewModel = new AppointmentViewModel
{
AppointmentId = appointment.AppointmentId,
ItemDescriptionId = appointment.ItemDescriptionId
};
Suggested refactoring:
private IEnumerable<SearchItems> GetItems(Guid lastId = new Guid())
{
IOrderedQueryable<ItemDescription> items= _itemDescriptionRepository.FindAll();
if(!items.Any())
ModelState.AddModelError("", string.Format("No active {0} entered.", Kids.Resources.Entities.ItemDescription.EntityNamePlural));
return items
.OrderBy(c => c.Description).Where(a=>a.IsActive == true || a.ItemDescriptionId == lastId)
.Select(c => new SearchItems {Text = c.Description, Value = c.ItemDescriptionId.ToString()});
}
It's silly to pass in the ViewModel when all your using it for is taking the necessary Guid. Then call it like
viewModel.Items= GetItems(appointment.ItemDescriptionId);
If you're query still isnt adding the correct item try debugging it like.
var testExists = itemDescriptionRepository.FindAll().FirstOrDefault(a.ItemDescriptionId == lastId);
If you're not finding it, and you're certain lastId is set correctly, it's probably a database issue.

Categories

Resources