So I have a custom ViewModel (CompanySalaryDataViewModel) that has a collection of other ViewModels on it (PersonalIncomeViewModel). Ultimately, I want to have an EditorTemplate for a CompanySalaryDataViewModel that consumes an EditorTemplate for a PersonalIncomeViewModel somehow in a way that it provides 2-way binding to my ViewModel when it’s passed back into my POST controller.
For example, let’s say it’s something like this:
public class CompanySalaryDataViewModel
{
string CompanyName { get; set; }
IList<PersonalIncomeViewModel> AllSalaryData { get; set; }
}
public class PersonalIncomeViewModel
{
long UniqueID { get; set; }
string PersonName { get; set; }
int JanIncome { get; set; }
int FebIncome { get; set; }
int MarIncome { get; set; }
int AprIncome { get; set; }
int MayIncome { get; set; }
int JunIncome { get; set; }
int JulIncome { get; set; }
int AugIncome { get; set; }
int SepIncome { get; set; }
int OctIncome { get; set; }
int NovIncome { get; set; }
int DecIncome { get; set; }
}
I want this done in a way where it’s similar to the following markup but works:
<%= Html.TextBoxFor(x => x.CompanyName) %>
<table cellspacing="0">
<thead>
<tr class="t-grid-header">
<th class="t-header">ID</th>
<th class="t-header">Person</th>
<th class="t-header">Jan</th>
<th class="t-header">Feb</th>
<th class="t-header">Mar</th>
<th class="t-header">Apr</th>
<th class="t-header">May</th>
<th class="t-header">Jun</th>
<th class="t-header">Jul</th>
<th class="t-header">Aug</th>
<th class="t-header">Sep</th>
<th class="t-header">Oct</th>
<th class="t-header">Nov</th>
<th class="t-header">Dec</th>
</tr>
</thead>
<%
var isAlt = false;
foreach (var salaryData in Model.AllSalaryData)
{
var salary = salaryData;
if (isAlt)
{%>
<tr class="t-alt">
<%
}
else
{%>
<tr>
<%
}
isAlt = !isAlt;
%>
<td><%=Html.TextBoxFor(x => salary.UniqueID)%></td>
<td><%=Html.TextBoxFor(x => salary.PersonName)%></td>
<td><%=Html.TextBoxFor(x => salary.JanIncome, new {id = salary.PersonName + "_1", style = "width: 45px;"})%></td>
<td><%=Html.TextBoxFor(x => salary.FebIncome, new {id = salary.PersonName + "_2", style = "width: 45px;"})%></td>
<td><%=Html.TextBoxFor(x => salary.MarIncome, new {id = salary.PersonName + "_3", style = "width: 45px;"})%></td>
<td><%=Html.TextBoxFor(x => salary.AprIncome, new {id = salary.PersonName + "_4", style = "width: 45px;"})%></td>
<td><%=Html.TextBoxFor(x => salary.MayIncome, new {id = salary.PersonName + "_5", style = "width: 45px;"})%></td>
<td><%=Html.TextBoxFor(x => salary.JunIncome, new {id = salary.PersonName + "_6", style = "width: 45px;"})%></td>
<td><%=Html.TextBoxFor(x => salary.JulIncome, new {id = salary.PersonName + "_7", style = "width: 45px;"})%></td>
<td><%=Html.TextBoxFor(x => salary.AugIncome, new {id = salary.PersonName + "_8", style = "width: 45px;"})%></td>
<td><%=Html.TextBoxFor(x => salary.SepIncome, new {id = salary.PersonName + "_9", style = "width: 45px;"})%></td>
<td><%=Html.TextBoxFor(x => salary.OctIncome, new {id = salary.PersonName + "_10", style = "width: 45px;"})%></td>
<td><%=Html.TextBoxFor(x => salary.NovIncome, new {id = salary.PersonName + "_11", style = "width: 45px;"})%></td>
<td><%=Html.TextBoxFor(x => salary.DecIncome, new {id = salary.PersonName + "_12", style = "width: 45px;"})%></td>
</tr>
<%
}%>
</table>
The problems with this code are:
- Each “January” textbox has the same name (
salary.JanIncome– doesn’t include anything to differentiate it from another salary). Same problem with every month. - Perhaps because of problem #1, this doesn’t bind back to the ViewModel when I post – my
AllSalaryDatacollection is null. - All of this seems VERY non-best-practice and like there should be a better way to do this.
Ultimately, I guess I need to better understand using templates with collections but the other part of it is the “logic” to properly apply the t-alt class to the appropriate table row.
NOTE #1: I set the HTML IDs this way for some javascript stuff I have interacting with these textboxes.
NOTE #2: I’m not really doing this with salary data.
Okay, so I have found a function solution that’s not ideal but it works. Apparently the
foreachis the problem but afor(var i=0; i < xxx.Count; i++)works because the index number gets used for generation of the name of the rendered control. Not ideal but this works perfectly.