Creating a matrix of checkboxes which supports post back in ASP.NET MVC

眉间皱痕 提交于 2019-12-06 16:31:20

As always, start with a view model(s) to represent what you want to display/edit.

public class RoleVM
{
    public int ID { get; set; }
    public string Name { get; set; }
    public List<CompanyVM> Companies { get; set; }
}
public class CompanyVM
{
    public int ID { get; set; }
    public string Name { get; set; }
    public bool IsSelected { get; set; }
}

and in the GET method

[HttpGet]
public ActionResult Index()
{
    IEnumerable<Role> roles = db.Roles;
    IEnumerable<Company> companies = db.Companies;
    List<RoleVM> model = roles.Select(x => new RoleVM()
    {
        ID = x.ID,
        Name = x.Name,
        Companies = companies.Select(y => new CompanyVM()
        {
            ID = y.ID,
            Name = y.Name
        }).ToList()
    }).ToList();
    // For editing existing roles, set the IsSelected property
    // of the respective CompanyVM to true
    return View(model);
}

and the view

@model List<RoleVM>
@using (Html.BeginForm())
{
    <table>
        <thead>
            <tr>
                <th>Company/Role</th>
                @foreach(var company in Model.FirstOrDefault().Companies)
                {
                    <th>@company.Name</th>
                }
            </tr>
        </thead>
        <tbody>
            @for (int i = 0; i < Model.Count; i++)
            {
                <tr>
                    <td>
                        @Model[i].Name
                        @Html.HiddenFor(m => m[i].ID)
                        @Html.HiddenFor(m => m[i].Name)
                    </td>
                    @for (int j = 0; j < Model[i].Companies.Count; j++)
                    {
                        <td>
                            @Html.HiddenFor(m => m[i].Companies[j].ID)
                            @Html.HiddenFor(m => m[i].Companies[j].Name)
                            @Html.CheckBoxFor(m => m[i].Companies[j].IsSelected)
                        </td>
                    }
                </tr>
            }
        </tbody>
    </table>    
    <button type="submit">Save</button>
}

which will the post to

[HttpPost]
public ActionResult Index(List<RoleVM> model)
{
    // To get the companies for each role
    foreach (var role in model)
    {
        var selectedCompanies = role.Companies.Where(x => x.IsSelected);

Note that using nested foreach loops would never have bound correctly when submitting your form (you need to use for loops). If you want to use EditorTemplates (your properties can be IEnumerable<T> rather that IList<T>, then create a partial in /Views/Shared/EditorTemplates/RoleVM.cshtml

@model RoleVM
<tr>
    <td>
        @Model.Name
        @Html.HiddenFor(m => m.ID)
        @Html.HiddenFor(m => m.Name)
    </td>
    @Html.EditorFor(m => m.Companies)
</tr>

and another for /Views/Shared/EditorTemplates/CompanyVM.cshtml

@model CompanyVM
<td>
     @Html.HiddenFor(m => m.ID)
     @Html.HiddenFor(m => m.Name)
     @Html.CheckBoxFor(m => m.IsSelected)
</td>

and the main view would be

@model List<RoleVM>
.... // as above
<tbody>
    @Html.EditorFor(m => m)
</tbody>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!