I made a LINQ Statement to fill a ViewBag and display it on my View, however for some reason my ListBox displays empty so i saved the LINQ statement on a txt file to see if it was empty, but it has the correct data, so my question is:
Why my ViewBag is not Displaying on my ListBox in my View?
This is my Linq Filling the ViewBag:
foreach (var item in db.VENTA_PLATILLOS
.Select(v => new { Turno = v.Nombre_Turno, Total = v.Total })
.GroupBy(l => l.Turno)
.AsEnumerable()
.Select(z => new { Turno = z.Key, Total = String.Format("{0:$#,##0.00;($#,##0.00);Zero}", Decimal.Round(z.Sum(l => l.Total), 0)) })
.OrderByDescending(a => a.Turno))
{
listadesumas.Add(string.Format("{{{0}, Total = {1}}}", item.Turno, item.Total));
}
//txt file to see if Linq Statemnt is filled correctly and it is
var json5 = JsonConvert.SerializeObject(listadesumas);
System.IO.File.WriteAllText(#"C:\inetpub\wwwroot\SumasTurno.txt", json5);
//Filling my Viewbag with my LinQ Group By Result
var grupos = new SelectList(listadesumas.ToList());
ViewBag.Group = grupos;
This is my View ListBox:
#{
var group = (SelectList)ViewBag.Group;
}
#Html.ListBox("Group", (IEnumerable<SelectListItem>)ViewBag.Group, new { style = "width: 300px;" })
Try the following in your controller instead...
ViewBag["Group"] = grupos;
...and this in the view...
#Html.ListBox("Group", (IEnumerable<SelectListItem>)ViewBag["Group"], new { style = "width: 300px;" })
I have tried your example as best as I could without knowing the underlying database table. I have not found an issue and found that it does render the option list correctly through a viewbag property containing a select list. So in this example, I stubbed in a string list for the underlying database table. In this example, I am able to populate the option list through the viewbag property containing the resulting a list. I have to wonder if your conclusion that it is not displaying is related to contents of the viewbag property "Group"
My example code:
public ActionResult Index()
{
List<string> listadesumas = new List<string>();
var FakeDbTable = new List<string>() { "a.bc", "a.cde", "b.xyz" };
foreach (var item in FakeDbTable.Select(v=> new { itemname = v })
.GroupBy(l => l.itemname.Substring(0, 1)).AsEnumerable().Select(z =>new { GroupingValue= z.Key, Total=string.Format("count {0}",z.Count())}).OrderByDescending(a=>a.GroupingValue))
{
listadesumas.Add(string.Format(" result item {0}",item));
}
var grupos = new SelectList(listadesumas.ToList());
ViewBag.Group = grupos;
return View();
}
The view code
#{
ViewBag.Title = "Home Page";
var group = (SelectList)ViewBag.Group;
}
<div class="row">
<div class="col-md-12">
#Html.ListBox("Group", (IEnumerable<SelectListItem>)ViewBag.Group, new { style = "max-width: 500px;" })
</div>
</div>
Result shows as this:
Related
I have a form with a MultiSelectList and I'm using .Net validation to require a selection be made amongst required other vields. When I submit, the multiple selections are sent to the controller correctly but if requirements aren't met, ModelState is invalid, I return back to the form. I'm using the below line to set the ViewBag instance of the MultiSelectList with the selections that were made. The code seems to work. However, the view only displays a single selection, the first selection, not any of the others that were sent and returned.
ViewBag.SelectedServiceLines = new MultiSelectList(db.LookUps.Where(lu => lu.RecordType == "ServLine"), "ID", "Description", funder.SelectedServiceLines.Select(i => i));
If I step through the razor code in my view I can view the ViewData and see that there is a MultiSelectList and it does have all of the selections that were sent to the controller and then returned. But only one of those selections are displayed. Below is how I'm displaying the list. I can't figure out why only one item is being displayed and not the multiple that get sent back and are in the ViewBag as "SelectedItems" for the MultiSelectList.
#Html.DropDownList("SelectedBusinessLines", null, htmlAttributes: new { #class = "form-control chosen-select", #multiple = "multiple" })
You can use either MultiSelectList or IEnumerable<SelectListItem>, depending on your choice:
// MultiSelectList approach
ViewBag.SelectedServiceLines = new MultiSelectList(db.LookUps.Where(lu => lu.RecordType == "ServLine"), "ID", "Description", funder.SelectedServiceLines.ToList());
// IEnumerable<SelectListItem> approach
ViewBag.SelectedServiceLines = db.LookUps.Where(lu => lu.RecordType == "ServLine")
.Select(i => new SelectListItem() {
Text = i.Description,
Value = i.Id,
Selected = funder.SelectedServiceLines.Contains(i.Id)
}).ToList();
Then use ListBox[For] helper instead of DropDownList[For] to create <select> element with multiple attribute:
#* MultiSelectList approach *#
#Html.ListBoxFor(model => model.SelectedBusinessLines, ViewBag.SelectedServiceLines as MultiSelectList, new { #class = "form-control chosen-select", #multiple = "multiple" })
#* IEnumerable<SelectListItem> approach *#
#Html.ListBoxFor(model => model.SelectedBusinessLines, ViewBag.SelectedServiceLines as IEnumerable<SelectListItem>, new { #class = "form-control chosen-select", #multiple = "multiple" })
Note that the ViewBag properties have dynamic type, you need to cast into respective type to avoid view rendering problem.
Side note
You may try create a MultiSelectList or IEnumerable<SelectListItem> property inside viewmodel:
public MultiSelectList SelectedServiceLines { get; set; }
And populate it with same way as ViewBag mentioned above:
var model = new ViewModel(); // use your viewmodel class name
model.SelectedServiceLines = new MultiSelectList(db.LookUps.Where(lu => lu.RecordType == "ServLine"), "ID", "Description", funder.SelectedServiceLines.ToList());
return View(model);
Then use it with ListBoxFor helper, but this time without any cast unlike ViewBag does:
#Html.ListBoxFor(model => model.SelectedBusinessLines, Model.SelectedServiceLines, new { #class = "form-control chosen-select", #multiple = "multiple" })
Can you try this instead? I've always used a List<SelectListItem> instead of a MultiSelectList:
// Use List<SelectListItem> instead
ViewBag.SelectedServiceLines =
db.LookUps
.Where(lu => lu.RecordType == "ServLine")
.Select(i => new SelectListItem() { Text = i.Description, Value = i.Id })
.ToList();
I also suggest using a ListBox instead:
#Html.ListBox("SelectedBusinessLines", ViewBag.SelectedBusinessLines, htmlAttributes: new { #class = "form-control chosen-select", #multiple = "multiple" })
I have an ASP.NET MVC view where I'm using LINQ to split a model into multiple lists of an object.
The code below works in that I get the correct list of objects in var data but I cannot then cast it to my object to access the properties. I get error
Unable to cast object of type
'Grouping[<>f__AnonymousType3'2[System.DateTime,System.String],MVCProj.Models.tblData2017]'
to type 'MVCProj.Models.tblData2017
Index.cshtml View:
#model IEnumerable<MVCProj.Models.tblData2017>
#{
ViewBag.Title = "Index";
}
<h2>Title</h2>
#{
var data = Model.Where(x => x.Start.Date == DateTime.UtcNow.Date)
.GroupBy(x => new { x.Start, x.Field2 }).ToList();
for (int i = 0; i < data.Count; i++)
{
var rowItem = (List<tblCards2017>)data[i]; //<-Error on this line
string header1 = $"{rowItem.Start.ToString("HH:mm")} {rowItem.Field2}";
}
}
How can I do either of the following
i) Successfully cast var rowItem = (List<tblCards2017>)data[i];
or
ii) Use linq to get the correct object type List<List<tblCards2017> data = Model.Where..... instead of the current type var data = System.Collections.Generic.List<System.Linq.IGrouping<<>f__AnonymousType2<System.DateTime, string>, MVCProj.Models.tblData2017>>
I think you are looking this:
var data = Model.Where(x => x.Start.Date == DateTime.UtcNow.Date)
.GroupBy(x => new { x.Start, x.Field2 })
.Select(g=>g.ToList()).ToList();
Add a Select call to get a list per each group
First thing, I have pre-defined model from existing db.
I just want to show existing value on edit page with MVC 5.
Here's what I have done:
Controller
public async Task<ActionResult> Edit(Guid? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
slik_data_a01 slik_data_a01 = await db.slik_data_a01.FindAsync(id);
if (slik_data_a01 == null)
{
return HttpNotFound();
}
//init DD
var selectedjs = (from x in db.master_segmenfasilitas
where x.sandi == slik_data_a01.kode_jenis_segmen
select new { x.fasilitas, x.sandi }).FirstOrDefault();
var jenissegmen = new SelectList((from x in db.master_segmenfasilitas
select new { x.fasilitas, x.sandi }).ToList(), "sandi", "fasilitas", selectedjs);
ViewBag.jenissegmen = jenissegmen;
return View(slik_data_a01);
}
And my view is like this :
<div class="form-group">
#Html.LabelFor(model => model.kode_jenis_segmen, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.kode_jenis_segmen, ViewBag.jenissegmen as SelectList, new{ #class = "form-control input-sm" })
#Html.ValidationMessageFor(model => model.kode_jenis_segmen, "", new { #class = "text-danger" })
</div>
</div>
but the default value always shows the first data of the SelectList,
not the existing one, although I have defined the selected values on controller.
Any help really appreciated.
You need to set the selected value in the model property that is binded with the DropDownListFor helper before passing the object to View method at last line and you don't need to set the selected value in the SelectList constructor, so change the SelectList creation code to be:
var jenissegmen = new SelectList((from x in db.master_segmenfasilitas
select new { x.fasilitas, x.sandi }).ToList(),
"sandi",
"fasilitas");
and before passing model set selected value in the model property, and helper will take care itself for selecting the value:
slik_data_a01.kode_jenis_segmen = selectedjs;
ViewBag.jenissegmen = jenissegmen;
return View(slik_data_a01);
Now the control will set the selected value on the basis of the value coming in the property which is binded with it.
Hope it helps!
I have been trying all the way around to solve this and the simple answer is i cannot assign selected value on model that doesn't have relation in the model.
The only way is that i need to update my model, or create another model which represent my data in the form (CMIIW).
But i found a simple hack, that doesn't require changes in the model, still not perfect but its just fine for me.
here's my updated controller :
public async Task<ActionResult> Edit(Guid? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var slik_data_a01 = await db.slik_data_a01.FindAsync(id);
if (slik_data_a01 == null)
{
return HttpNotFound();
}
//init Dropdown Data
ViewBag.jenissegmen = new SelectList((from x in db.master_segmenfasilitas
select new { x.fasilitas, x.sandi }).ToList()
/*OrderByDescending to put the selected value on first row*/
.OrderByDescending(o => o.sandi == slik_data_a01.kode_jenis_segmen)
, "sandi", "fasilitas");
//then return to the view.
return View(slik_data_a01);
}
and the view still using the Html.DropDownListFor
I saw this, however I have a different Q. I have a view like this:
#model myPrj.Models.RollCallModel
...
<table>
<tr> //Master DDL
<td>
#Html.LabelFor(model => model.CourseID)
#Html.DropDownListFor(model => model.CourseID,
new SelectList(new myPrj.Models.myDbContext().Courses
.Where(c => c.StatusID == 0), "ID", "ID"),
"choose...", new { id = "ddlCourse"})
#Html.ValidationMessageFor(model => model.CourseID)
</td>
</tr>
<tr> //Detail DDL
<td>
#Html.LabelFor(model => model.PersonnelID)
#Html.DropDownListFor(model => model.PersonnelID,
null, "choose another...", new { id = "ddlPersonnel"})
#Html.ValidationMessageFor(model => model.PersonnelID)
</td>
</tr>
</table>
...
I know enough about cascading updates with jquery. My Q is that is it possible to perform a cascade update to these DDLs without needing to write an iteration of <option>something</option> for the Detail DDL? If no, what's the handiest alternative?
note: In fact I'm trying to render the detail DDL with html helper because of the convention of model binding. If I have no choice but to render it by <select id=""></select>, how can I bind this select element to the model?
thanx
Update: It seems that there's no way... (still waiting and indeed searching...)
Yeah! of course there is: See this for details. However it needs an additional action method and a partial view for each Detail DDL.
finally I like to decide to go through JQuery and iterationally adding <options> over the JsonResult...
To populate a dropdownlist in MVC use this as an alternative in your View:
#Html.DropDownListFor(model => model.CourseID, new SelectList((IList<SelectListItem>)ViewData["MyCourse"],
"Value", "Text"), new { #class = "span5" })
Supporting the View you should write the following in the corresponding controller action:
public ActionResult RoleList(int id)
{
ViewData["MyCourse"] = FillCourseList(id);
CourseModel model = new CourseModel();
model.courseid= id;
return View(model);
}
To fill ViewData you need a corresponding function in the same controller which is as follows:
public IList<SelectListItem> FillCourseList(int id)
{
List<master_tasks> lst = new List<master_tasks>();
lst = _taskInterface.getMasterTasks();
IList<SelectListItem> items = new List<SelectListItem>();
items.Add(new SelectListItem
{
Text = "Select Task",
Value = "0"
});
for (int i = 0; i < lst.Count; i++)
{
items.Add(new SelectListItem
{
Text = lst[i].code + " - " + lst[i].name,
Value = lst[i].id.ToString()
});
}
return items;
}
IList is a generic list with list item typecasted for Html.Dropdownlistfor IEnumerable items.
I just want to select the first item by default but the drop down list has a blank item selected.
How I can resolve it? Thank you!
[Authorize]
public ActionResult Add()
{
var sportList = new SelectList(db.Sports.OrderBy(s => s.Name).ToList(), "ID", "Name");
UserTournamentModel m = new UserTournamentModel();
m.SportList = sportList;
m.SportID = Guid.Parse(sportList.FirstOrDefault().Value);
return View(m);
}
and here
<div class="editor-label" style="width: 70px;">
#Html.DropDownListFor(x => x.SportID, Model.SportList)
</div>
Use the SelectList constructor overload that accepts the selected item:
var orderedSportList = db.Sports.OrderBy(s => s.Name);
var sportList = new SelectList(orderedSportList.ToList(), "ID", "Name",
orderedSportList.FirstOrDefault());