Reputation: 95
In a razor view, how can I loop through different IEnumerables in a ViewModel and display their variables as columns in the same row?
I Return an instance of a viewmodel which is populated with IEnumerables of different models to a mvc view like so:
Viewmodel:
namespace example.ViewModels
{
public class ClaimModel
{
public IEnumerable<Claim> Claims { get; set; }
public IEnumerable<Member> Members { get; set; }
public IEnumerable<ID> IDs { get; set; }
}
}
My controller which return the view looks like this:
namespace example.Controllers
{
public class OfficeManagerController : Controller
{
private Entities db = new Entities(); //This is my database
public ActionResult Index()
{
IEnumerable<Member> member = db.Members.OrderByDescending(b => b.ClaimID);
IEnumerable<Claim> claim = db.Claims.OrderByDescending(b => b.ClaimID);
IEnumerable<ID> id = db.IDs;
ClaimModel model = new ClaimModel { IDs = id, Members = member, Claims = claim };
return View(model);
}
}
}
Here is a snippet of my razor view where i loop through one of the IEnumerables in my viewmodel called Members
:
@model example.ViewModels.ClaimModel
<div class="table list-group ">
<div class="row table-bordered ">
<div class="pull-left col-xs-1 h5">
Claim ID:
</div>
<div class="pull-left col-xs-2 h5">
Member Name:
</div>
<div class="pull-left col-xs-2 h5">
Member ID:
</div>
</div>
@foreach (var item in Model.Members)
{
<div class="pull-left col-xs-1 h5">
@Html.DisplayFor(modelItem => item.ClaimID)
</div>
<div class="pull-left col-xs-2 ">
@Html.DisplayFor(modelItem => item.Name)
</div>
<div class="pull-left col-xs-2 ">
@Html.DisplayFor(modelItem => item.MemberID)
</div>
}
</div>
This is a regular way of looping through one of the IEnumerables. Of course I don't need a ViewModel to accomplish this because I might as well just pass my Members IEnumerable straight into my view.
Now what logic do I have to apply in order to display data from the three different IEnumerables into columns of the same row? I imagine its possible with razor.
I need something like this:
@model example.ViewModels.ClaimModel
<div class="table list-group ">
<div class="row table-bordered ">
<div class="pull-left col-xs-1 h5">
Member Name:
</div>
<div class="pull-left col-xs-2 h5">
Claim Name:
</div>
<div class="pull-left col-xs-2 h5">
ID Name:
</div>
</div>
@foreach (var item in Model.Members)
{
<div class="pull-left col-xs-1 h5">
@Html.DisplayFor(modelItem => item.Name)
</div>
}
@foreach (var item in Model.Claims)
{
<div class="pull-left col-xs-1 h5">
@Html.DisplayFor(modelItem => item.Name)
</div>
}
@foreach (var item in Model.IDs)
{
<div class="pull-left col-xs-1 h5">
@Html.DisplayFor(modelItem => item.Name)
</div>
}
However this will not insert my variables into the same rows but will stack all the members names next to one another and so on.
I am adding here thanks to comment below that every Claim
has a Member
and an ID
. Claim
has a primary key called ClaimID
and Member
and ID
are related to it with foreign keys called ClaimID
.
Upvotes: 1
Views: 2850
Reputation: 218722
Assuming all three collections has same item count and you want to show the nth item in all the lists on the nth row of the table in 3 columns, this should work.
<table class="table table-striped">
@{ var rowCounter = 0;}
@foreach (var item in Model.Members)
{
<tr>
<td>
@item.Name
</td>
<td>
@if (Model.Claims.Count()>= rowCounter)
{
<span>@Model.Claims[rowCounter].Name</span>
}
</td>
<td>
@if (Model.IDs.Count()>= rowCounter)
{
<span>@Model.IDs[rowCounter].Name</span>
}
</td>
</tr>
rowCounter++;
}
</table>
While this solve your problem, I strongly suggest you change your approach. You should do a join in your controller and send a list of items with all these 3 properties and do a simple loop and display in your razor view.
So create a view model to represent your grid data
public class ClaimRecord
{
public string ClaimName {set;get;}
public string MemberName {set;get;}
public int Id {set;get;}
}
and in your action method, join the three data sets and project the needed results a collection of this class and send to the view
var list = new List<ClaimRecord>();
//to do: Add items to the list here
// I don't know the relation between these 3 data sets. So i can't tell yo how to do that.
// But basically, if you have forign key relationship or so, you need to do a join
return View(list);
and in your view
@model List<ClaimRecord>
<table>
@foreach(var item in Model)
{
<tr>
<td>@item.Id</td>
<td>@item.ClaimName</td>
<td>@item.MemberName</td>
</tr>
}
</table>
EDIT : As per the comment.
Claim has a primary key called ClaimID and Member and ID are related to it with foreign keys called ClaimID.
You can do a join with your LINQ expression.
var list = (from a in db.Claims
join b in db.Members on a.ClaimID equals b.ClaimID
join c in db.IDs on a.ClaimID equals c.ClaimID
select new ClaimRecord {
Id = a.ClaimID, //Update these as needed
MemberName = b.MemberName,
ClaimName = a.ClaimName }).ToList();
return View(list);
Please update the projection part with your property names.(My code assumes that Member table/Entity has a MemberName column/property and Claim table has a ClaimName property. Update that part according to your needs.
Upvotes: 2