ASP.Net MVC: How to generate html table using edit

2019-09-20 15:02发布

问题:

still now i generate html table like below code example but interested to know how could i generate html table using editorfor using editor template

see my full razor and view model code and guide me how to achieve my goal.

@model MVCCRUDPageList.Models.StudentListViewModel
@{
    ViewBag.Title = "Index";
}

<h2>CREATE TABULAR UI WITH HTML TABLE</h2>

@using (Html.BeginForm("Index", "HtmlTable", FormMethod.Post))
{
    <div class="form-group">
        <div class="col-md-12 table-responsive">
            <table class="table table-bordered table-hover">
                <tr>
                    <th>
                        Row No
                    </th>
                    <th>
                        ID
                    </th>
                    <th>
                        Name
                    </th>
                    <th>
                        Country
                    </th>
                    <th>
                        Hobbies
                    </th>
                    <th>
                        Sex
                    </th>
                </tr>
                }

                @for (int x=0; x<=Model.Students.Count-1;x++)
                {
                    <tr>
                        <td>
                            <label>@(x+1)</label>
                        </td>
                        <td>
                            @Html.TextBoxFor(m => m.Students[x].ID)
                        </td>
                        <td>
                            @Html.TextBoxFor(m => m.Students[x].Name)
                        </td>
                        <td>
                            @Html.DropDownListFor(m => m.Students[x].CountryID,
                              new SelectList(Model.Country, "ID", "Name",  Model.Students[x].CountryID),
                             "-- Select Countries--", new { id = "cboCountry", @class = "edit-mode" })
                        </td>
                        <td>
                            @for (var i = 0; i < Model.Students.FirstOrDefault().Hobbies.Count; i++)
                            {
                                <div class="checkbox">
                                    @Html.HiddenFor(m => m.Students[x].Hobbies[i].ID)
                                    @Html.HiddenFor(m => m.Students[x].Hobbies[i].Name)
                                    @Html.CheckBoxFor(m => m.Students[x].Hobbies[i].Checked)
                                    @Html.LabelFor(m => m.Students[x].Hobbies[i].Name, Model.Students[x].Hobbies[i].Name)
                                </div>
                            }

                        </td>
                        <td>
                            @for (var i = 0; i < Model.Sex.Count; i++)
                            {
                                <div class="checkbox">
                                    @Html.HiddenFor(m => Model.Sex[i].ID)
                                    @Html.HiddenFor(m => Model.Sex[i].SexName)
                                    @Html.RadioButtonFor(m => m.Students[x].SexID, Model.Sex[i].ID)
                                    @Html.LabelFor(m => m.Students[x].SexID, Model.Sex[i].SexName)
                                </div>
                            }
                        </td>
                    </tr>
                }
            </table>
        </div>

        <input type="submit" value="Submit" />
    </div>
}

View Model Code

public class StudentListViewModel
{
    public IList<Student> Students { get; set; }
    public List<Country> Country { get; set; }
    public List<Sex> Sex { get; set; }


    public StudentListViewModel()
    {
        Students = new List<Student>
        {
            new Student
            {
                ID=1,Name="Keith",CountryID=0,SexID="F",
                Hobbies= new List<Hobby>
                {
                    new Hobby{ID=1,Name="Football",Checked=false},
                    new Hobby{ID=2,Name="Hocky",Checked=false},
                    new Hobby{ID=3,Name="Cricket",Checked=false}
                }

            },

            new Student
            {
                ID=2,Name="Paul",CountryID=2,
                Hobbies= new List<Hobby>
                {
                    new Hobby{ID=1,Name="Football",Checked=false},
                    new Hobby{ID=2,Name="Hocky",Checked=false},
                    new Hobby{ID=3,Name="Cricket",Checked=false}
                }
            },

            new Student
            {
                ID=3,Name="Sam",CountryID=3,
                Hobbies= new List<Hobby>
                {
                    new Hobby{ID=1,Name="Football",Checked=false},
                    new Hobby{ID=2,Name="Hocky",Checked=false},
                    new Hobby{ID=3,Name="Cricket",Checked=false}
                }
            }
        };

        Country = new List<Country>
        {
            new Country{ID=1,Name="India"},
            new Country{ID=2,Name="UK"},
            new Country{ID=3,Name="USA"}
        };

        Sex = new List<Sex>
        {
            new Sex{ID="M",SexName="Male"},
            new Sex{ID="F",SexName="Female"}
        };

    }
}

please guide me how to restructure my razor code to use editorfor and editor template for clean code. what will be name of editor template ?

thanks

回答1:

To use an EditorTemplate using @Html.EditorFor(m => m.SomeProperty) (where SomeProperty is a complex object, or collection of complex objects), then the template must be located in the /Views/Shared/EditorTemplates or /Views/YourControllerName/EditorTempates folder, and be named the same as the class name for SomeProperty.

In your case, if you want an EditorTemplate for typeof Student, then the template (a partial view) will be named Student.cshtml.

@model yourAssembly.Student
<tr>
    <td>@Html.TextBoxFor(m => m.ID)</td>
    <td>@Html.TextBoxFor(m => m.Name)<td>
    ....
<tr>

and in the main view, your would use

<table>
    <thead> .... </thead>
    <tbody>
        @Html.EditorFor(m => m.Students)
    </tbody>
</table>

which will generate the correct html for each item in your collection.

However, since you also have a dropdownlist for CountryID, then you need to pass the SelectList to the template (the template has no knowledge of the parent model) using additionalViewData, so the code needs to be modified to

@Html.EditorFor(m => m.Students, new { Countries = Model.Countries})

where the Countries property in StudentListViewModel should be

public IEnumerable<SelectListItem> Countries { get; set; }

and delete you current List<Country> Country property. Then in the view generate the dropdownlist using

<td>@Html.DropDownListFor(m => m.CountryID, (IEnumerable<SelectListItem>)ViewData["Countries "], "-- Select Country--", new { ... })<td>

Note you should not be adding new { id = "cboCountry" } because its creating invalid html (duplicate id attribute).

Now you can extend this further by creating an EditorTemplate for Hobby (which will be named Hobby.cshtml

@model yourAssembly.Hobby
<div class="checkbox">
    @Html.HiddenFor(m => m.ID)
    @Html.HiddenFor(m => m.Name)
    @Html.CheckBoxFor(m => m.Checked)
    @Html.LabelFor(m => m.Checked, Model.Name)
</div>

Note the LabelFor() should be for the Checked property, not the Name property as you currently have it.

Then in your Student.cshtml template, use

<td>@Html.EditorFor(m => m.Hobbies)<td>

to generate the correct html for each Hobby.