Reputation: 135
I have an MVC app that I am trying to put together that requires some select lists and drop down lists.
So, I have the following models....
public class Task
{
public int ID { get; set; }
public string Title { get; set; }
......
public virtual ICollection<Monitor> Monitors { get; set; }
public virtual ICollection<Resource> Resources { get; set; }
}
public class Monitor
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public IList<Task> Tasks { get; set; }
}
public class Resource
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
.....
public IList<Task> Tasks { get; set; }
The interesting part is that when I display a list of tasks, among the other properties that display just fine, I need to display a list of 'Monitors' and a list of 'Resources' that are assigned to the task in the Index view shown below.
@model IEnumerable<ResourceManager.Models.Task>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
.....
<th>
@Html.DisplayNameFor(model => model.Title)
</th>
.....
<th>
@Html.DisplayNameFor(model => model.Monitors)
</th>
<th>
@Html.DisplayNameFor(model => model.Resources)
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
.....
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
.....
<td>
@if (item.Monitors == null || item.Monitors.Count == 0)
{<span>No Monitors Assigned</span>}
else
{ string.Join(", ", item.Monitors.Select(m => string.Format("{0} {1}", m.FirstName, m.LastName))); }
</td>
<td>
@Html.DisplayFor(modelItem => item.Resources)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
@Html.ActionLink("Details", "Details", new { id=item.ID }) |
@Html.ActionLink("Delete", "Delete", new { id=item.ID })
</td>
</tr>
}
</table>
And here is the controller....
public ActionResult Index()
{
var tasks = from t in db.Tasks where t.IsActive == true select t;
return View(tasks);
}
I would like for the list of Monitors and the list of Resources to display as a string on the Index, Delete and Details Views i.e. 'Monitor 1, Monitor 2, Monitor 3' and 'Resource 1, Resource 2, Resource 3'.
However on the other views (Create and Edit), I want them to appear as a selectable list.
Upvotes: 1
Views: 16504
Reputation: 4288
Try as follows,
var monitors = //Your linq query List monitorList = new List(); foreach (var monitor in monitors ){ SelectListItem item = new SelectListItem(); item.Text = monitor.FirstName; item.Value = monitor.Id.ToString(); monitorList .Add(item); } ViewData["ddlList"] = monitorList;
Upvotes: 0
Reputation: 239270
For the display of Monitors/Resources (and since you want them displayed as a comma-delimited list), you can just use string.Join
:
<td>
@string.Join(",", Model.Monitors.Select(m => string.Format("{0} {1}", m.FirstName, m.LastName)))
</td>
To be able to actually use Html.DisplayFor
, you'd have to create a custom display template so Razor will actually know how to respond. To do so, in your Views folder, create new folder called "DisplayTemplates", and in that, create a new partial view called "Monitors.cshtml" and "Resources.cshtml", strongly-typed to IEnumerable<Monitor>
and IEnumerable<Resource>
, respectively. Then inside that file, you'll just add roughly the same code as above:
@model IEnumerable<Monitor>
@string.Join(",", Model.Select(m => string.Format("{0} {1}", m.FirstName, m.LastName)))
Then in your view, you can call:
@Html.DisplayFor(m => m.Monitors, "Monitors")
Unfortunately, in this example, you'd have to feed the template name because the default behavior of DisplayFor
for a list, is to render the display template multiple times, once for each member of the list. You could do something like:
# Monitor.cshtml
@model Monitor
@Model.FirstName @Model.LastName,
And then:
@Html.DisplayFor(m => m.Monitors)
But your last item would have a comma at the end.
For editing the lists, all you have to do is pass the select lists to your view. Optimally, you'd do this with a view model, but for simplicity's sake, I'll just use ViewBag
here. In your controller action:
ViewBag.MonitorChoices = db.Monitors.Select(m => new SelectListItem
{
Value = m.ID.ToString(),
Text = string.Format("{0} {1}", m.FirstName, m.LastName)
});
Then, in your create/edit view:
@Html.ListBoxFor(m => m.Monitors, ViewBag.MonitorChoices)
Upvotes: 4
Reputation: 4288
First Create Select list in your controller,
var monitors = //Your linq query ViewData["ddlList"] = monitors .Select(x => new SelectListItem { Text = x.FirstName, Value = x.Id.ToString() }).ToList();
And then you can use it in your view as follows,
<%=Html.DropDownList("myList") %>
Upvotes: 6