Jay Davis
Jay Davis

Reputation: 135

MVC and Entity Framework Select List

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

Answers (3)

Jatin patil
Jatin patil

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

Chris Pratt
Chris Pratt

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

Jatin patil
Jatin patil

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

Related Questions